Added, edited, corrected and completed the AbstractProtocol doxygen documentation

This commit is contained in:
Srivats P. 2010-04-18 21:50:35 +05:30
parent 0075a3712b
commit ae05037265
3 changed files with 289 additions and 67 deletions

View File

@ -26,20 +26,49 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
/*!
\class AbstractProtocol
\todo (MED) update AbstractProtocol documentation
Bare Minimum set of methods that a subclass needs to reimplement
AbstractProtocol is the base abstract class which provides the interface
for all protocols.
All protocols supported by Ostinato are derived from AbstractProtocol. Apart
from defining the interface for a protocol, it also provides sensible default
implementations for methods so that the subclasses need not re-implement. It
also provides convenience functions for subclasses to use such as methods to
retrieve payload size, checksum etc.
A subclass typically needs to reimplement the following methods -
- name()
- shortName()
- createInstance()
- protocolNumber()
- protoDataCopyInto() [pure virtual]
- protoDataCopyFrom() [pure virtual]
- fieldCount()
- fieldFlags()
- fieldData()
- setFieldData()
- configWidget() [pure virtual]
- loadConfigWidget() [pure virtual]
- storeConfigWidget() [pure virtual]
Any useful protocol should also provide implementations for
- name()
- shortName()
- fieldName()
Depending on certain conditions, subclasses may need to reimplement the
following additional methods -
- protocolIdType()
- protocolId()
- protocolFrameSize()
- isProtocolFrameValueVariable()
- isProtocolFrameSizeVariable()
Protocols with meta fields should additionally implement
- metaFieldCount()
- isMetaField()
See the description of the methods for more information.
Most of the above methods just need some standard boilerplate code -
the SampleProtocol implementation includes the boilerplate
*/
/*!
Constructs an abstract protocol for the given stream and parent
parent is typically NULL except for protocols which are part of a
ComboProtocol
*/
AbstractProtocol::AbstractProtocol(StreamBase *stream, AbstractProtocol *parent)
{
@ -51,16 +80,31 @@ AbstractProtocol::AbstractProtocol(StreamBase *stream, AbstractProtocol *parent)
protoSize = -1;
}
/*!
Destroys the abstract protocol
*/
AbstractProtocol::~AbstractProtocol()
{
}
/*!
Allocates and returns a new instance of the class.
Caller is responsible for freeing up after use. Subclasses MUST implement
this function
*/
AbstractProtocol* AbstractProtocol::createInstance(StreamBase* /* stream */,
AbstractProtocol* /* parent */)
{
return NULL;
}
/*!
Returns the protocol's field number as defined in message 'Protocol', enum 'k'
(file: protocol.proto)
Subclasses MUST implement this function
*/
quint32 AbstractProtocol::protocolNumber() const
{
qFatal("Something wrong!!!");
@ -68,29 +112,44 @@ quint32 AbstractProtocol::protocolNumber() const
}
/*!
\fn virtual void protoDataCopyInto(OstProto::OstProto::StreamCore &stream) = 0;
\fn virtual void AbstractProtocol::protoDataCopyInto(OstProto::Protocol &protocol) const = 0
Copy the protocol's protobuf into the passed in stream \n
In the base class this is a pure virtual function. Subclasses should
implement this function by using - \n
stream.AddExtension(<ExtId>)->CopyFrom(<protobuf_data>) */
Copy the protocol's protobuf as an extension into the passed in protocol
/*
\fn virtual void protoDataCopyFrom(const OstProto::OstProto::StreamCore &stream) = 0;
*/
In the base class this is a pure virtual function. Subclasses MUST implement
this function. See the SampleProtocol for an example
*/
/*! Returns the full name of the protocol \n
The default implementation returns a null string */
/*!
\fn virtual void AbstractProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol) = 0
Copy and update the protocol's protobuf member data variable from the
passed in protocol
In the base class this is a pure virtual function. Subclasses MUST implement
this function. See the SampleProtocol for an example
*/
/*!
Returns the full name of the protocol
The default implementation returns a null string
*/
QString AbstractProtocol::name() const
{
return QString();
}
/*! Returns the short name or abbreviation of the protocol \n
The default implementation forms and returns a abbreviation composed
/*!
Returns the short name or abbreviation of the protocol
The default implementation forms and returns an abbreviation composed
of all the upper case chars in name() \n
The default implementation caches the abbreviation on its first invocation
and subsequently returns the cached abbreviation */
and subsequently returns the cached abbreviation
*/
QString AbstractProtocol::shortName() const
{
if (protoAbbr.isNull())
@ -109,19 +168,27 @@ QString AbstractProtocol::shortName() const
return protoAbbr;
}
/*! Returns the number of fields (both Frame and Meta fields) \n
The default implementation returns zero */
int AbstractProtocol::fieldCount() const
/*!
Returns the number of fields in the protocol (both Frame fields and
Meta fields)
The default implementation returns zero. Subclasses MUST implement this
function.
*/
int AbstractProtocol::fieldCount() const
{
return 0;
}
/*! Returns the number of meta fields \n
/*!
Returns the number of meta fields
The default implementation counts and returns the number of fields for which
the FieldIsMeta flag is set\n
The default implementation caches the count on its first invocation
and subsequently returns the cached count */
int AbstractProtocol::metaFieldCount() const
and subsequently returns the cached count
*/
int AbstractProtocol::metaFieldCount() const
{
if (metaCount < 0)
{
@ -135,24 +202,35 @@ int AbstractProtocol::metaFieldCount() const
return metaCount;
}
/*! Returns the number of frame fields \n
Convenience method - same as fieldCount() minus metaFieldCount() */
int AbstractProtocol::frameFieldCount() const
/*!
Returns the number of frame fields
Convenience method - same as fieldCount() minus metaFieldCount()
*/
int AbstractProtocol::frameFieldCount() const
{
//qDebug("%s:%d, %d", __FUNCTION__, fieldCount(), metaFieldCount());
return (fieldCount() - metaFieldCount());
}
/*!
Returns the field flags for the passed in field index
The default implementation assumes all fields to be frame fields and returns
'FieldIsNormal'. Subclasses must reimplement this method if they have any
meta fields or checksum fields. See the SampleProtocol for an example.
*/
AbstractProtocol::FieldFlags AbstractProtocol::fieldFlags(int /*index*/) const
{
return FieldIsNormal;
}
/*! Returns the requested field attribute data \n
/*!
Returns the requested field attribute data
Protocols which have meta fields that vary a frame field across
streams may use the streamIndex to return the appropriate field value \n
Some field attriubutes e.g. FieldName may be invariant across streams\n
The default implementation returns the fieldValue() converted to string
Some field attributes e.g. FieldName may be invariant across streams\n
The FieldTextValue attribute may include additional information about
the field's value e.g. a checksum field may include "(correct)" or
"(incorrect)" alongwith the actual checksum value. \n
@ -167,14 +245,14 @@ AbstractProtocol::FieldFlags AbstractProtocol::fieldFlags(int /*index*/) const
fields whose size are a non-integral multiple of bytes or smaller than
a byte, subclasses should return the correct value. Also for fields
which represent checksums, subclasses should return a value for
FieldBitSize - even if it is an integral multiple of bytes
FieldBitSize - even if it is an integral multiple of bytes.
\note If a subclass uses any of the below functions to derive
FieldFrameValue, the subclass should handle and return a value for
FieldBitSize to prevent endless recrusion -
- protocolFrameCksum()
- protocolFramePayloadSize()
*/
*/
QVariant AbstractProtocol::fieldData(int index, FieldAttrib attrib,
int streamIndex) const
{
@ -203,25 +281,58 @@ QVariant AbstractProtocol::fieldData(int index, FieldAttrib attrib,
return QVariant();
}
/*! Sets the value of a field corresponding to index \n
Returns true if field is successfully set, false otherwise \n
The default implementation always returns false */
/*!
Sets the value of a field corresponding to index
This method is called by the GUI code to store a user specified value into
the protocol's protoBuf. Currently this method is called with
FieldAttrib = FieldValue only.
Returns true if field is successfully set, false otherwise.
The default implementation always returns false. Subclasses should
reimplement this method. See SampleProtocol for an example.
*/
bool AbstractProtocol::setFieldData(int /*index*/, const QVariant& /*value*/,
FieldAttrib /*attrib*/)
{
return false;
}
/*!
Returns the protocolIdType for the protocol
The default implementation returns ProtocolIdNone. If a subclass has a
protocolId field it should return the appropriate value e.g. IP protocol
will return ProtocolIdIp, Ethernet will return ProtocolIdEth etc.
*/
AbstractProtocol::ProtocolIdType AbstractProtocol::protocolIdType() const
{
return ProtocolIdNone;
}
/*!
Returns the protocol id of the protocol for the given type
The default implementation returns 0. If a subclass represents a protocol
which has a particular protocol id, it should return the appropriate value.
If a protocol does not have an id for the given type, it should defer to
the base class. e.g. IGMP will return 2 for ProtocolIdIp, and defer to the
base class for the remaining ProtocolIdTypes; IP will return 0x800 for
ProtocolIdEth type, 0x060603 for ProtocolIdLlc and 0x04 for ProtocolIdIp etc.
*/
quint32 AbstractProtocol::protocolId(ProtocolIdType /*type*/) const
{
return 0;
}
/*!
Returns the protocol id of the payload protocol (the protocol that
immediately follows the current one)
A subclass which has a protocol id field, can use this to retrieve the
appropriate value
*/
quint32 AbstractProtocol::payloadProtocolId(ProtocolIdType type) const
{
quint32 id;
@ -237,6 +348,16 @@ quint32 AbstractProtocol::payloadProtocolId(ProtocolIdType type) const
return id;
}
/*!
Returns the protocol's size in bytes
The default implementation sums up the individual field bit sizes and
returns it. The default implementation calculates the caches the size on
the first invocation and subsequently returns the cached size.
If the subclass protocol has a varying protocol size, it MUST reimplement
this method, otherwise the default implementation is sufficient.
*/
int AbstractProtocol::protocolFrameSize(int streamIndex) const
{
if (protoSize < 0)
@ -255,6 +376,13 @@ int AbstractProtocol::protocolFrameSize(int streamIndex) const
return protoSize;
}
/*!
Returns the byte offset in the packet where the protocol starts
This method is useful only for "padding" protocols i.e. protocols which
fill up the remaining space for the user defined packet size e.g. the
PatternPayload protocol
*/
int AbstractProtocol::protocolFrameOffset(int streamIndex) const
{
int size = 0;
@ -272,6 +400,12 @@ int AbstractProtocol::protocolFrameOffset(int streamIndex) const
return size;
}
/*!
Returns the size of the payload in bytes. The payload includes all protocols
subsequent to the current
This method is useful for protocols which need to fill in a payload size field
*/
int AbstractProtocol::protocolFramePayloadSize(int streamIndex) const
{
int size = 0;
@ -289,11 +423,14 @@ int AbstractProtocol::protocolFramePayloadSize(int streamIndex) const
}
/*! Returns a byte array encoding the protocol (and its fields) which can be
/*!
Returns a byte array encoding the protocol (and its fields) which can be
inserted into the stream's frame
The default implementation forms and returns an ordered concatenation of
the FrameValue of all the 'frame' fields of the protocol taking care of fields
which are not an integral number of bytes\n */
the FrameValue of all the 'frame' fields of the protocol also taking care of
fields which are not an integral number of bytes\n
*/
QByteArray AbstractProtocol::protocolFrameValue(int streamIndex, bool forCksum) const
{
QByteArray proto, field;
@ -386,16 +523,38 @@ QByteArray AbstractProtocol::protocolFrameValue(int streamIndex, bool forCksum)
return proto;
}
/*!
Returns true if the protocol varies one or more of its fields at run-time,
false otherwise
The default implementation returns false. A subclass should reimplement
if it has varying fields e.g. an IP protocol that increments/decrements
the IP address with every packet
*/
bool AbstractProtocol::isProtocolFrameValueVariable() const
{
return false;
}
/*!
Returns true if the protocol varies its size at run-time, false otherwise
The default implmentation returns false. A subclass should reimplement
if it varies its size at run-time e.g. a Payload protocol for a stream with
incrementing/decrementing frame lengths
*/
bool AbstractProtocol::isProtocolFrameSizeVariable() const
{
return false;
}
/*!
Returns true if the payload content for a protocol varies at run-time,
false otherwise
This is useful for subclasses which have fields dependent on payload content
(e.g. UDP has a checksum field that varies if the payload varies)
*/
bool AbstractProtocol::isProtocolFramePayloadValueVariable() const
{
AbstractProtocol *p = next;
@ -412,6 +571,13 @@ bool AbstractProtocol::isProtocolFramePayloadValueVariable() const
return false;
}
/*!
Returns true if the payload size for a protocol varies at run-time,
false otherwise
This is useful for subclasses which have fields dependent on payload size
(e.g. UDP has a checksum field that varies if the payload varies)
*/
bool AbstractProtocol::isProtocolFramePayloadSizeVariable() const
{
AbstractProtocol *p = next;
@ -428,14 +594,17 @@ bool AbstractProtocol::isProtocolFramePayloadSizeVariable() const
return false;
}
/*!
Returns the checksum (of the requested type) of the protocol's contents
Useful for protocols which have a checksum field
\note If a subclass uses protocolFrameCksum() from within fieldData() to
derive a cksum field, it MUST handle and return the 'FieldBitSize'
attribute also for that particular field instead of using the default
AbstractProtocol implementation for 'FieldBitSize' - this is required
to prevent infinite recursion
*/
*/
quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
CksumType cksumType) const
{
@ -502,6 +671,14 @@ quint32 AbstractProtocol::protocolFrameCksum(int streamIndex,
return cksum;
}
/*!
Returns the checksum of the requested type for the protocol's header
This is useful for subclasses which needs the header's checksum e.g. TCP/UDP
require a "Pseudo-IP" checksum
Currently the default implementation supports only type CksumIpPseudo
*/
quint32 AbstractProtocol::protocolFrameHeaderCksum(int streamIndex,
CksumType cksumType) const
{
@ -530,6 +707,15 @@ quint32 AbstractProtocol::protocolFrameHeaderCksum(int streamIndex,
return (quint16) ~sum;
}
/*!
Returns the checksum of the requested type for the protocol's payload
This is useful for subclasses which needs the payload's checksum e.g. TCP/UDP
require a IP checksum of the payload (to be combined with other checksums to
derive the final checksum)
Currently the default implementation supports only type CksumIp
*/
quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
CksumType cksumType) const
{
@ -558,3 +744,33 @@ quint32 AbstractProtocol::protocolFramePayloadCksum(int streamIndex,
return (quint16) ~sum;
}
/*!
\fn virtual QWidget* AbstractProtocol::configWidget() = 0;
Returns the configuration widget for the protocol. The protocol retains
ownership of the configuration widget - the caller should not free it.
In the base class this is a pure virtual function. Subclasses MUST implement
this function. See the SampleProtocol for an example
*/
/*!
\fn virtual void AbstractProtocol::loadConfigWidget() = 0;
Loads data from the protocol's protobuf into the configuration widget of
the protocol
In the base class this is a pure virtual function. Subclasses MUST implement
this function. See the SampleProtocol for an example
*/
/*!
\fn virtual void AbstractProtocol::storeConfigWidget() = 0;
Stores data from the configuration widget of the protocol into the protocol's
protobuf
In the base class this is a pure virtual function. Subclasses MUST implement
this function. See the SampleProtocol for an example
*/

View File

@ -48,45 +48,49 @@ class AbstractProtocol
friend class ProtocolListIterator;
private:
mutable int metaCount;
mutable int protoSize;
mutable int metaCount;
mutable int protoSize;
mutable QString protoAbbr;
protected:
StreamBase *mpStream;
AbstractProtocol *parent;
AbstractProtocol *prev;
AbstractProtocol *next;
StreamBase *mpStream; //!< Stream that this protocol belongs to
AbstractProtocol *parent; //!< Parent protocol, if any
AbstractProtocol *prev; //!< Protocol preceding this protocol
AbstractProtocol *next; //!< Protocol succeeding this protocol
public:
//! Properties of a field, can be OR'd
enum FieldFlag {
FieldIsNormal = 0x0,
FieldIsMeta = 0x1,
FieldIsCksum = 0x2
FieldIsNormal = 0x0, //!< field appears in frame content
FieldIsMeta = 0x1, //!< field does not appear in frame, is meta data
FieldIsCksum = 0x2 //!< field is a checksum, appears in frame content
};
Q_DECLARE_FLAGS(FieldFlags, FieldFlag);
Q_DECLARE_FLAGS(FieldFlags, FieldFlag); //!< \private abcd
//! Various attributes of a field
enum FieldAttrib {
FieldName, //! name
FieldValue, //! value in host byte order (user editable)
FieldTextValue, //! value as text
FieldFrameValue, //! frame encoded value in network byte order
FieldBitSize, //! size in bits
FieldName, //!< name
FieldValue, //!< value in host byte order (user editable)
FieldTextValue, //!< value as text
FieldFrameValue, //!< frame encoded value in network byte order
FieldBitSize, //!< size in bits
};
//! Supported Protocol Id types
enum ProtocolIdType {
ProtocolIdNone,
ProtocolIdLlc,
ProtocolIdEth,
ProtocolIdIp,
ProtocolIdNone, //!< Marker representing non-existent protocol id
ProtocolIdLlc, //!< LLC (802.2)
ProtocolIdEth, //!< Ethernet II
ProtocolIdIp, //!< IP
};
//! Supported checksum types
enum CksumType {
CksumIp,
CksumIpPseudo,
CksumTcpUdp,
CksumIp, //!< Standard IP Checksum
CksumIpPseudo, //!< Standard checksum for Pseudo-IP header
CksumTcpUdp, //!< Standard TCP/UDP checksum including pseudo-IP
CksumMax
CksumMax //!< Marker for number of cksum types
};
AbstractProtocol(StreamBase *stream, AbstractProtocol *parent = 0);

View File

@ -30,6 +30,7 @@ SampleConfigForm::SampleConfigForm(QWidget *parent)
SampleProtocol::SampleProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent)
{
/* The configWidget is created lazily */
configForm = NULL;
}
@ -459,6 +460,7 @@ bool SampleProtocol::isProtocolFrameSizeVariable() const
QWidget* SampleProtocol::configWidget()
{
/* Lazy creation of the configWidget */
if (configForm == NULL)
{
configForm = new SampleConfigForm;