Packet.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00033 #include "Qt.h"
00034 #include "Packet.h"
00035 #include "Bye.h"
00036 #include "Ping.h"
00037 #include "Pong.h"
00038 #include "Push.h"
00039 #include "Query.h"
00040 #include "QueryHits.h"
00041 #include "QueryRouting.h"
00042 #include "QueryRoutingPatch.h"
00043 #include "QueryRoutingReset.h"
00044 #include "UnknownPacket.h"
00045 #include "VendorMessages/VendorMessage.h"
00046
00047 using namespace Gnutella::Packets;
00048
00050
00053 QDataStream & Gnutella::Packets::operator>> (QDataStream &in, PayloadDescriptor &pd)
00054 {
00055 uchar tmp;
00056 in >> tmp;
00057 pd = static_cast<PayloadDescriptor> (tmp);
00058 return in;
00059 }
00060
00062
00065 QDataStream & Gnutella::Packets::operator<< (QDataStream &out, const PayloadDescriptor &pd)
00066 {
00067 return out << static_cast<uchar> (pd);
00068 }
00069
00071
00075 QDataStream & Gnutella::Packets::operator>> (QDataStream &in, QHostAddress &ha)
00076 {
00077 QDataStream::ByteOrder oldByteOrder = in.byteOrder();
00078 in.setByteOrder (QDataStream::BigEndian);
00079 quint32 ipAddress;
00080 in >> ipAddress;
00081 ha.setAddress (ipAddress);
00082 in.setByteOrder (oldByteOrder);
00083 return in;
00084 }
00085
00087
00091 QDataStream & Gnutella::Packets::operator<< (QDataStream &out, const QHostAddress &ha)
00092 {
00093 QDataStream::ByteOrder oldByteOrder = out.byteOrder();
00094 out.setByteOrder (QDataStream::BigEndian);
00095 out << ha.toIPv4Address();
00096 out.setByteOrder (oldByteOrder);
00097 return out;
00098 }
00099
00101
00109 QDataStream & Gnutella::Packets::operator>> (QDataStream &in, Extensions::Extension &extension)
00110 {
00111 extension.read (in);
00112 return in;
00113 }
00114
00116
00124 QDataStream & Gnutella::Packets::operator<< (QDataStream &out, const Extensions::Extension &extension)
00125 {
00126 extension.write (out);
00127 return out;
00128 }
00129
00141 Packet * Packet::fromRawData (const QByteArray &rawHeader, const QByteArray &rawPayload)
00142 {
00143 int payloadDescriptor = static_cast <uchar> (rawHeader[16]);
00144
00145
00146 #ifdef NO_PACKET_VIRTUAL_CTOR
00147 return 0;
00148 #endif
00149
00150 switch (static_cast <uchar> (payloadDescriptor))
00151 {
00152 case PingDescriptor:
00153 return new Ping (rawHeader, rawPayload);
00154 case PongDescriptor:
00155 return new Pong (rawHeader, rawPayload);
00156 case QueryDescriptor:
00157 return new Query (rawHeader, rawPayload);
00158 case QueryHitsDescriptor:
00159 return new QueryHits (rawHeader, rawPayload);
00160 case PushDescriptor:
00161 return new Push (rawHeader, rawPayload);
00162 case QueryRoutingDescriptor:
00163 {
00164 QueryRouting::Variant variant = QueryRouting::UnknownVariant;
00165 if (rawPayload.length() > 0)
00166 variant = static_cast <QueryRouting::Variant> (rawPayload[0]);
00167
00168 switch (variant){
00169 case QueryRouting::ResetVariant:
00170 return new QueryRoutingReset (rawHeader, rawPayload);
00171 case QueryRouting::PatchVariant:
00172 return new QueryRoutingPatch (rawHeader, rawPayload);
00173 case QueryRouting::UnknownVariant:
00174 default:
00175 return new UnknownPacket (rawHeader, rawPayload);
00176 }
00177 }
00178 case ByeDescriptor:
00179 return new Bye (rawHeader, rawPayload);
00180 case IbmcDescriptor:
00181 case OpenVendorDescriptor:
00182 case StandardVendorDescriptor:
00183 return VendorMessages::VendorMessage::fromRawData (rawHeader, rawPayload);
00184 default:
00185 return new UnknownPacket (rawHeader, rawPayload);
00186 }
00187 }
00188
00197 Packet::Packet(PayloadDescriptor payloadDescriptor)
00198 {
00199 d = new Data;
00200
00201 d->ref.init (1);
00202
00203 d->descriptorId = QUuid::createUuid();
00204 d->hops = DefaultHops;
00205 d->ttl = DefaultTtl;
00206 d->payloadDescriptor = payloadDescriptor;
00207 d->payloadLength = 0;
00208
00209 d->rewriteHeader = true;
00210 d->rewritePayload = true;
00211 d->isValid = true;
00212 }
00213
00226 Packet::Packet (const QByteArray &rawHeader, const QByteArray &rawPayload)
00227 {
00228 d = new Data;
00229
00230 d->ref.init (1);
00231
00232 d->rawHeader = rawHeader;
00233 d->rawPayload = rawPayload;
00234 d->rewriteHeader = false;
00235 d->rewritePayload = false;
00236 d->isValid = false;
00237 }
00238
00240
00243 Packet::~Packet()
00244 {
00245 if (!d->ref.deref())
00246 delete d;
00247 }
00248
00250
00253 Packet & Packet::operator= (const Packet &other)
00254 {
00255 qAtomicAssign (d, other.d);
00256 return *this;
00257 }
00258
00262 void Packet::invalidateHeader()
00263 {
00264 qAtomicDetach(d);
00265 d->ref.init(1);
00266 d->rewriteHeader = true;
00267 }
00268
00279 void Packet::invalidatePayload()
00280 {
00281 invalidateHeader();
00282 d->rewritePayload = true;
00283 }
00284
00297 void Packet::parse()
00298 {
00299 Q_ASSERT (d->ref == 1);
00300
00301 d->isValid = true;
00302 if (prepareReadHeader (d->rawHeader)) {
00303 QDataStream headerStream (d->rawHeader);
00304 headerStream.setByteOrder (QDataStream::LittleEndian);
00305 readHeader (headerStream);
00306 } else
00307 d->isValid = false;
00308
00309 Q_ASSERT (d->payloadLength == static_cast <uint> (d->rawPayload.length()));
00310
00311 if (prepareReadPayload (d->rawPayload)) {
00312 QDataStream payloadStream (d->rawPayload);
00313 payloadStream.setByteOrder (QDataStream::LittleEndian);
00314 readPayload (payloadStream);
00315 } else
00316 d->isValid = false;
00317 }
00318
00322 bool Packet::prepareReadHeader (const QByteArray &rawHeader) const
00323 {
00324 return rawHeader.length() == HeaderLength;
00325 }
00326
00336 void Packet::readHeader (QDataStream &stream)
00337 {
00338 stream >> d->descriptorId;
00339 stream >> d->payloadDescriptor;
00340 stream >> d->ttl;
00341 stream >> d->hops;
00342 stream >> d->payloadLength;
00343 }
00344
00354 void Packet::writeHeader (QDataStream &stream) const
00355 {
00356 stream << d->descriptorId;
00357 stream << d->payloadDescriptor;
00358 stream << d->ttl;
00359 stream << d->hops;
00360 stream << d->payloadLength;
00361 }
00362
00388 QByteArray Packet::rawHeader() const
00389 {
00390 if (!isValid())
00391 return QByteArray();
00392
00393 if (d->rewriteHeader) {
00394
00395 if (d->rewritePayload)
00396 rawPayload();
00397
00398
00399 d->rawHeader.resize (HeaderLength);
00400
00401
00402 QDataStream stream (&d->rawHeader, QIODevice::WriteOnly);
00403 stream.setByteOrder (QDataStream::LittleEndian);
00404 writeHeader (stream);
00405
00406
00407 Q_ASSERT (d->rawHeader.length() == HeaderLength);
00408 d->rawHeader.resize (HeaderLength);
00409
00410 d->rewriteHeader = false;
00411 }
00412 return d->rawHeader;
00413 }
00414
00441 QByteArray Packet::rawPayload() const
00442 {
00443 if (!isValid())
00444 return QByteArray();
00445
00446 if (d->rewritePayload) {
00447
00448 d->payloadLength = prepareWritePayload();
00449 d->rawPayload.resize (d->payloadLength);
00450
00451
00452 QDataStream stream (&d->rawPayload, QIODevice::WriteOnly);
00453 stream.setByteOrder (QDataStream::LittleEndian);
00454 writePayload (stream);
00455
00456
00457
00458
00459
00460 Q_ASSERT (d->payloadLength ==
00461 static_cast <uint> (d->rawPayload.length()));
00462 d->rawPayload.resize (d->payloadLength);
00463
00464 d->rewritePayload = false;
00465 }
00466 return d->rawPayload;
00467 }
00468