GgepBlock.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
00023 #include "Qt.h"
00024 #include "GgepBlock.h"
00025 #include "Ggep.h"
00026
00027 using namespace Gnutella::Packets::Extensions;
00028
00029 GgepBlock::GgepBlock()
00030 : Extension(), extensions_(), rawBlockLength_()
00031 {
00032 setIsValid (true);
00033 }
00034
00035 GgepBlock::GgepBlock (const GgepBlock &block)
00036 : Extension(), extensions_(), rawBlockLength_()
00037 {
00038 foreach (const Ggep *extension, block.extensions_)
00039 addExtension (*extension);
00040 }
00041
00042 GgepBlock * GgepBlock::copy() const
00043 {
00044 return new GgepBlock (*this);
00045 }
00046
00047 GgepBlock& GgepBlock::operator= (const GgepBlock &block)
00048 {
00049 if (this == &block)
00050 return *this;
00051
00052 foreach (const Ggep *extension, extensions_)
00053 delete extension;
00054
00055 extensions_.clear();
00056 foreach (const Ggep *extension, block.extensions_)
00057 addExtension (*extension);
00058
00059 return *this;
00060 }
00061
00062 GgepBlock::~GgepBlock()
00063 {
00064 deleteExtensions();
00065 }
00066
00067 void GgepBlock::deleteExtensions()
00068 {
00069 foreach (const Ggep *extension, extensions_)
00070 delete extension;
00071 extensions_.clear();
00072 }
00073
00074 int GgepBlock::prepareRead (const QByteArray &rawData)
00075 {
00076 deleteExtensions();
00077
00078 setIsValid (false);
00079 int rawDataSize = rawData.size();
00080 rawBlockLength_ = rawDataSize;
00081
00082
00083 if (rawDataSize < 4)
00084 return 0;
00085
00086 int currentPos = 0;
00087 if (rawData[currentPos++] != MagicByte)
00088 return 0;
00089
00090 bool isLastExtension = false;
00091 while (!isLastExtension) {
00092
00093 uchar flags = rawData[currentPos++];
00094 isLastExtension = flags & Ggep::LastExtension;
00095 int idLength = flags & Ggep::IDLength;
00096
00097
00098 if (currentPos + idLength + 1 > rawDataSize)
00099 return 0;
00100
00101 Ggep::GgepId id (rawData.data() + currentPos, idLength);
00102 currentPos += idLength;
00103
00104 int dataLength = 0;
00105 bool readMore = false;
00106 int bytesRead = 0;
00107 do {
00108 char byte = rawData[currentPos++];
00109 dataLength = (dataLength << 6) | (byte & 0x3F);
00110 readMore = (byte & 0x40) != 0x40;
00111 bytesRead++;
00112 } while (readMore && bytesRead < 3 && currentPos < rawDataSize);
00113
00114 if (readMore)
00115 return 0;
00116
00117 if (currentPos + dataLength > rawDataSize)
00118 return 0;
00119
00120 if (currentPos + dataLength == rawDataSize)
00121 isLastExtension = true;
00122
00123 currentPos += dataLength;
00124
00125 Ggep *extension = Ggep::fromId (id, flags, dataLength);
00126 Q_ASSERT (extension != 0);
00127 extensions_.append (extension);
00128
00129
00130
00131
00132 int rawExtensionDataStart = currentPos - dataLength;
00133 int rawExtensionDataLength = currentPos - rawExtensionDataStart;
00134 QByteArray extensionData = QByteArray::fromRawData (rawData.data() + rawExtensionDataStart, rawExtensionDataLength);
00135
00136 extension->prepareRead (extensionData);
00137 }
00138 setIsValid (true);
00139 return currentPos;
00140 }
00141
00142 void GgepBlock::read (QDataStream &stream)
00143 {
00144
00145
00146
00147
00148 if (!isValid()) {
00149 deleteExtensions();
00150 QByteArray buffer;
00151 buffer.resize (rawBlockLength_);
00152 stream.readRawData (buffer.data(), rawBlockLength_);
00153 return;
00154 }
00155
00156 uchar temp;
00157 stream >> temp;
00158
00159 Q_ASSERT (temp == uchar (MagicByte));
00160
00161
00162
00163
00164
00165
00166
00167
00168 Ggep *extension = 0;
00169 foreach (const Ggep *constExtension, extensions_) {
00170 extension = const_cast <Ggep *> (constExtension);
00171 extension->read (stream);
00172 }
00173 }
00174
00175 int GgepBlock::prepareWrite() const
00176 {
00177 if (extensions_.count() == 0)
00178 return 0;
00179
00180 int writeBytesCount = 1;
00181
00182 foreach (const Ggep * extension, extensions_) {
00183 writeBytesCount += extension->prepareWrite();
00184 }
00185 return writeBytesCount;
00186 }
00187
00188 void GgepBlock::write (QDataStream &stream) const
00189 {
00190 if (extensions_.count() == 0)
00191 return;
00192
00193 stream << static_cast <uchar> (MagicByte);
00194
00195 foreach (const Ggep * extension, extensions_) {
00196 extension->write (stream);
00197 }
00198 }
00199
00200 void GgepBlock::addExtension (const Ggep &extension)
00201 {
00202 Ggep *newExtension = extension.copy();
00203 newExtension->setFlag (Ggep::LastExtension);
00204
00205 if (extensions_.size() > 0) {
00206 Ggep *oldLastExtension = const_cast <Ggep *> (extensions_.last());
00207 oldLastExtension->resetFlag (Ggep::LastExtension);
00208 }
00209 extensions_.append (newExtension);
00210 }
00211
00212 GgepBlock::Extensions GgepBlock::extensions() const
00213 {
00214 return extensions_;
00215 }