Gnutella::Packets::Packet Class Reference

#include <Packet.h> [code]

Inherited by Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::UnknownPacket, and Gnutella::Packets::VendorMessages::VendorMessage.

Inheritance diagram for Gnutella::Packets::Packet:

Inheritance graph
[legend]
Collaboration diagram for Gnutella::Packets::Packet:

Collaboration graph
[legend]
List of all members.

Detailed Description

Base class for all Gnutella packets.

A typical Gnutella packet consists of two parts: header and payload. All packet types share the same header structure but have different payload structure. The table below presents the data fields stored in a header and how they can be accessed using the Packet interface. For a detailed documentation of all basic Gnutella packets and the usage of all their fileds please refer to The Annotated Gnutella Protocol Specification v0.4.

Byte Offset Field Name getFunction setFunction
0..15 Descriptor ID descriptorId() N/A
16 Payload Descriptor payloadDescriptor()N/A
17 Time to Live ttl() setTtl()
18 Hops hops() setHops()
19..23 Payload Length payloadLength() setPayloadLength()

The Packet class is an abstract class that defines a common interface for all packets. You can create packets of type PingPacket, PongPacket, QueryPacket, QueryHitsPacket and PushPacket by using two types of constructors:

If you derive from Packet, make sure you provide implementation for isPayloadValid(), readPayload() and writePayload(). To support reading a Packet of the new class, you will also need to extend PacketReader::getPacket().

Todo:
Move the implementation completely in the .cpp. This will make the header nicer to read, but will make the use of the class more constly due to the out of line code expansion. When the implementation is stable, the functions may be declared as inline, and their implementation can be moved back to the header. This would genrally be made for the accessor functions, even if private data is used. It can be moved to the header as well. We would generally prefer using private data to separate the interface from its implementation. This way many headers need only be included in the .cpp but not in the .h, which would decrease the dependancies. Of course if the private data stores only pointers, then the headers need again only be included in the .cpp.
Todo:
Replace rawHeader() and rawPayload() with rawPacket(). This would make it intuitive for the packet writer to write all data at once making it UdpConnection compatible. There is no need for both functions anyway. Moreover, change fromRawData to take just const QByteArray &rawPacket.
See also:
PingPacket, PongPacket, QueryPacket, QueryHitsPacket, PushPacket

Definition at line 137 of file Packet.h.

Public Member Functions

virtual ~Packet ()
 Destructor.
virtual QString name () const =0
const QUuid & descriptorId () const
 Gets the descriptor ID header field.
PayloadDescriptor payloadDescriptor () const
 Gets the payload desctiptor header field.
uchar ttl () const
 Gets the ttl header field.
uchar hops () const
 Gets the hops header filed.
quint32 payloadLength () const
 Gets the payload length header field.
quint32 packetLength () const
 Gets the total packet length in bytes (header length + payload length).
bool isValid () const
 Checks if the packet is valid (has correct structure and valid data).
void doHop ()
 Increments hops and decrements ttl by one.
void setDescriptorId (const QUuid &descriptorId)
 Sets the descriptror ID header field.
void setTtl (uchar ttl)
 Sets the ttl header filed.
void setHops (uchar hops)
 Sets the hops header field.
QByteArray rawHeader () const
 Returns a QByteArray containing the raw header ready for transmission.
QByteArray rawPayload () const
 Returns a QByteArray containing the raw payload ready for transmission.
virtual Packetcopy () const =0
 A virtual copy contructor.

Static Public Member Functions

static PacketfromRawData (const QByteArray &rawHeader, const QByteArray &rawPayload)

Protected Member Functions

 Packet (PayloadDescriptor payloadDescriptor)
 Packet (const QByteArray &rawHeader, const QByteArray &rawPayload)
 Packet (const Packet &other)
Packetoperator= (const Packet &other)
 Assignment operator.
void setIsValid (bool isValid)
 Marks the packet as either valid or invalid.
void invalidateHeader ()
 Marks the header as modified. The header should be rebuilt next time rawHeader() is called.
virtual void invalidatePayload ()
 Marks the payload as modified. The payload should be rebuilt next time rawPayload() is called.
void parse ()
 Parses the raw header and payload and fills the packet fields.
virtual bool prepareReadPayload (const QByteArray &rawPayload)=0
 Verifies the structure of the rawPayload.
virtual void readPayload (QDataStream &stream)=0
 Reads the payload fields from the stream. The structure of the data in the stream is already verified by verifyPayload().
virtual int prepareWritePayload () const =0
 Gets ready to write the payload and returns the payload length.
virtual void writePayload (QDataStream &stream) const =0
 Writes the payload fields into the stream.

Private Member Functions

bool prepareReadHeader (const QByteArray &rawHeader) const
 Verifies the structure of the rawHeader.
void readHeader (QDataStream &stream)
 Reads the header fields from the stream. The structure of the data in the stream is verified by verifyHeader().
void writeHeader (QDataStream &stream) const
 Writes the header into the stream.

Private Attributes

Datad
 Private data with reference counting.

Friends

class Testing::ByeConcretePacket
class Testing::TestPacket

Classes

struct  Data
 Stores the private members of Packet. More...


Constructor & Destructor Documentation

Packet::~Packet  )  [virtual]
 

Destructor.

Destroys a Packet object.

Definition at line 243 of file Packet.cpp.

Packet::Packet PayloadDescriptor  payloadDescriptor  )  [protected]
 

Constructs a Packet object. payloadDescriptor is used to initialize the corresponding header field. The other fields are initialized with default values, which can later be changed using the setter functions.

Note:
Make sure payloadDescriptor matches the packet type you are implementing in the derived class.

Definition at line 197 of file Packet.cpp.

Packet::Packet const QByteArray &  rawHeader,
const QByteArray &  rawPayload
[protected]
 

Constructs a Packet object without setting any of the header fields. It just stores the passed rawHeader and rawPayload. This data is cached and returned when calling rawHeader() and rawPayload(). Refer to their documentation for more info on caching the raw data.

Note:
If you want that the header and payload fileds are initialized using the supplied raw bytes (and you will deffinitely want that), then simply call the parse() function from within the corresponding constructor of the derived class and it will do the rest! Clear enough, we cannot call parse() here directly as the object is still not completely created and polymorphism is not working for this object yet.

Definition at line 226 of file Packet.cpp.

Gnutella::Packets::Packet::Packet const Packet other  )  [inline, protected]
 

Definition at line 221 of file Packet.h.


Member Function Documentation

virtual Packet* Gnutella::Packets::Packet::copy  )  const [pure virtual]
 

A virtual copy contructor.

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, and Gnutella::Packets::VendorMessages::SupportedMessages.

const QUuid & Gnutella::Packets::Packet::descriptorId  )  const [inline]
 

Gets the descriptor ID header field.

Definition at line 225 of file Packet.h.

void Gnutella::Packets::Packet::doHop  )  [inline]
 

Increments hops and decrements ttl by one.

Definition at line 251 of file Packet.h.

Packet * Packet::fromRawData const QByteArray &  rawHeader,
const QByteArray &  rawPayload
[static]
 

This function plays the role of a virtual constructor. Once you have read the complete raw data for a packet (yes, you should be aware of the format in order to do this, see PacketReader), call this function, which will create an object calling new and return it. Make sure you delete the object when done with it.

Todo:
That would become part of the PacketFactory for Gnutella.
See also:
PacketReader

Reimplemented in Gnutella::Packets::VendorMessages::VendorMessage.

Definition at line 141 of file Packet.cpp.

uchar Gnutella::Packets::Packet::hops  )  const [inline]
 

Gets the hops header filed.

Definition at line 234 of file Packet.h.

void Packet::invalidateHeader  )  [protected]
 

Marks the header as modified. The header should be rebuilt next time rawHeader() is called.

Invalidates the header data, so that the rawHeader will be rebuilt next time it is needed.

Definition at line 262 of file Packet.cpp.

void Packet::invalidatePayload  )  [protected, virtual]
 

Marks the payload as modified. The payload should be rebuilt next time rawPayload() is called.

The header is invalidated, due to the fact that the payloadLength field may have changed, and the payload is marked as invalid too.

Note:
If you want to implement reference counting on the private data of the derived class, then override this function, but make sure you call the base class implementation.
See also:
invalidateHeader()

Reimplemented in Gnutella::Packets::Bye, Gnutella::Packets::Pong, and Gnutella::Packets::Testing::ByeConcretePacket.

Definition at line 279 of file Packet.cpp.

bool Gnutella::Packets::Packet::isValid  )  const [inline]
 

Checks if the packet is valid (has correct structure and valid data).

Definition at line 248 of file Packet.h.

virtual QString Gnutella::Packets::Packet::name  )  const [pure virtual]
 

Todo:
remove this?

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, and Gnutella::Packets::VendorMessages::SupportedMessages.

Packet & Packet::operator= const Packet other  )  [protected]
 

Assignment operator.

Copies other into this object. Copying is fast due to reference counting.

Definition at line 253 of file Packet.cpp.

quint32 Gnutella::Packets::Packet::packetLength  )  const [inline]
 

Gets the total packet length in bytes (header length + payload length).

Definition at line 245 of file Packet.h.

void Packet::parse  )  [protected]
 

Parses the raw header and payload and fills the packet fields.

The function checks the structure of the bytes in rawHeader and rawPayload by calling prepareReadHeader() and prepareReadPayload() respectively. If any of the functions returns false, then the packet is marked as invalid. If the functions return true, then a QStreamObject is created around the raw bytes and the functions readHeader() and readPayload() are called to read the packet fields out of the stream. If any of the function returns false, meaning that some field had an invalid value, then the packet is marked as invalid. You can check if a packet is OK by calling isValid(). You should discard the packet if the function returns false, as most probably some of the packet fields are not set!

Definition at line 297 of file Packet.cpp.

PayloadDescriptor Gnutella::Packets::Packet::payloadDescriptor  )  const [inline]
 

Gets the payload desctiptor header field.

Definition at line 228 of file Packet.h.

quint32 Gnutella::Packets::Packet::payloadLength  )  const [inline]
 

Gets the payload length header field.

Definition at line 237 of file Packet.h.

bool Packet::prepareReadHeader const QByteArray &  rawHeader  )  const [private]
 

Verifies the structure of the rawHeader.

Simply checks if the header is of correct size.

Definition at line 322 of file Packet.cpp.

bool Packet::prepareReadPayload const QByteArray &  rawPayload  )  [protected, pure virtual]
 

Verifies the structure of the rawPayload.

Verifies if the rawPayload can be correctly parsed by readPayload(). The function just goes over the whole rawPayload and checks if the structure of the payload is correct. Some data may be gathered and stored to ease the work of readPayload(). For example, the size of the query hit data field can only be calculated with knowledge of the payloadLength, which is not available in the QDataStream object passed to readPayload(). The size of this field is read here and stored for use later in readPayload().

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, Gnutella::Packets::VendorMessages::SupportedMessages, and Gnutella::Packets::VendorMessages::VendorMessage.

virtual int Gnutella::Packets::Packet::prepareWritePayload  )  const [protected, pure virtual]
 

Gets ready to write the payload and returns the payload length.

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, Gnutella::Packets::VendorMessages::SupportedMessages, and Gnutella::Packets::VendorMessages::VendorMessage.

QByteArray Packet::rawHeader  )  const
 

Returns a QByteArray containing the raw header ready for transmission.

The function returns a cached QByteArray containing the raw header bytes, unless the header was marked as modified by calling invalidateHeader(). In this case, the header is rebuilt by calling writeHeader() and cached for future use.

Caching of the packet's raw data improves performance especially when the same packet is sent to more than one peer. In this case, due to reference counting, the raw data is generated just once and is also stored just once, although the packets are copied in multiple connections.

Todo:
The above works like this only in the case when we forward a packet received from a peer. We do not change the payload and it is never rebuilt, thus all copies of the Packet share the same QByteArray for the rawPayload. In the case when we generate the packet, we first copy it in each PacketConnection and then call rawHeader() and rawPayload(). The raw data is built for each of the copies separately. Reference counting the Packet's Private data should solve the problem.
Returns:
A QByteArray containing the header's raw data.
Todo:
What happens if the payload changes (thus the payload size) and the header is rebuilt before the new payload change is recalculated? It's clear what happens, but check whether it really does!
See also:
rawPayload()

Definition at line 388 of file Packet.cpp.

QByteArray Packet::rawPayload  )  const
 

Returns a QByteArray containing the raw payload ready for transmission.

The function returns a cached QByteArray containing the raw payload bytes, unless the payload was marked as modified by calling invalidatePayload(). In this case, the payload is rebuilt by calling writePayload() and cached for future use.

Read the docs for rawHeader() for more info on raw data caching.

This function is called by rawHeader() and payloadLength() to ensure that the header field payloadLength has the correct value.

Todo:
Implement locking in case the private data is shared among some objects to ensure only one rebuilds the payload.
See also:
rawHeader()

Definition at line 441 of file Packet.cpp.

void Packet::readHeader QDataStream &  stream  )  [private]
 

Reads the header fields from the stream. The structure of the data in the stream is verified by verifyHeader().

Reads the header fields from the stream, which uses little endian byte order - Gnutella's default byte order. Some fields may be in big endian if explicitly stated in the specifications.

Todo:
The descriptor ID is said to be a 16 byte string, which implies big endianness if we consder it as a 4 + 2*2 + 8*1 bytes. Need to change byte order?

Definition at line 336 of file Packet.cpp.

virtual void Gnutella::Packets::Packet::readPayload QDataStream &  stream  )  [protected, pure virtual]
 

Reads the payload fields from the stream. The structure of the data in the stream is already verified by verifyPayload().

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, Gnutella::Packets::VendorMessages::SupportedMessages, and Gnutella::Packets::VendorMessages::VendorMessage.

void Gnutella::Packets::Packet::setDescriptorId const QUuid &  descriptorId  )  [inline]
 

Sets the descriptror ID header field.

Definition at line 254 of file Packet.h.

void Gnutella::Packets::Packet::setHops uchar  hops  )  [inline]
 

Sets the hops header field.

See also:
setTtl(), doHop()

Definition at line 260 of file Packet.h.

void Gnutella::Packets::Packet::setIsValid bool  isValid  )  [inline, protected]
 

Marks the packet as either valid or invalid.

Definition at line 263 of file Packet.h.

void Gnutella::Packets::Packet::setTtl uchar  ttl  )  [inline]
 

Sets the ttl header filed.

See also:
setHops(), doHop()

Definition at line 257 of file Packet.h.

uchar Gnutella::Packets::Packet::ttl  )  const [inline]
 

Gets the ttl header field.

Definition at line 231 of file Packet.h.

void Packet::writeHeader QDataStream &  stream  )  const [private]
 

Writes the header into the stream.

Writes the header fields into the stream, which uses little endian byte order - Gnutella's default byte order. Some fields may be in big endian if explicitly stated in the specifications.

Todo:
The descriptor ID is said to be a 16 byte string, which implies big endianness if we consder it as a 4 + 2*2 + 8*1 bytes. Need to change byte order?

Definition at line 354 of file Packet.cpp.

virtual void Gnutella::Packets::Packet::writePayload QDataStream &  stream  )  const [protected, pure virtual]
 

Writes the payload fields into the stream.

Implemented in Gnutella::Packets::Bye, Gnutella::Packets::Ping, Gnutella::Packets::Pong, Gnutella::Packets::Push, Gnutella::Packets::Query, Gnutella::Packets::QueryHits, Gnutella::Packets::QueryRouting, Gnutella::Packets::QueryRoutingPatch, Gnutella::Packets::QueryRoutingReset, Gnutella::Packets::UnknownPacket, Gnutella::Packets::VendorMessages::QueryStatusRequest, Gnutella::Packets::VendorMessages::QueryStatusResponse, Gnutella::Packets::VendorMessages::SupportedMessages, and Gnutella::Packets::VendorMessages::VendorMessage.


Friends And Related Function Documentation

friend class Testing::ByeConcretePacket [friend]
 

Definition at line 205 of file Packet.h.

friend class Testing::TestPacket [friend]
 

Definition at line 206 of file Packet.h.


Member Data Documentation

Data* Gnutella::Packets::Packet::d [private]
 

Private data with reference counting.

Reimplemented in Gnutella::Packets::Bye, and Gnutella::Packets::Pong.

Definition at line 203 of file Packet.h.


The documentation for this class was generated from the following files: