TrackerResponseParser.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 "PeerInfo.h"
00025 #include "TrackerResponseParser.h"
00026 #include "TrackerResponse.h"
00027 #include "Imports.cpp"
00028 #include <limits>
00029
00031
00058 bool TrackerResponseParser::parseAndLoadTrackerResponse (
00059 const QByteArray &rawTrackerResponseData,
00060 TrackerResponse &trackerResponse)
00061 {
00062 TrackerResponse parsedResponse;
00063
00064 bool loadedOk = loadAllResponseData (rawTrackerResponseData, parsedResponse);
00065 if (!loadedOk)
00066 return false;
00067
00068 trackerResponse = parsedResponse;
00069 return true;
00070 }
00071
00072
00074
00078 bool TrackerResponseParser::loadAllResponseData (const QByteArray &rawData,
00079 TrackerResponse &response)
00080 {
00081
00082 BDecoder bDecoder (rawData);
00083 auto_ptr <BItem> item = bDecoder.readNext();
00084 if (!bDecoder.hasReadAllCorrectly())
00085 return false;
00086
00087 const BDictionary *bData = dynamic_cast <const BDictionary *> (item.get());
00088 if (!bData || bData->keys().size() == 0)
00089 return false;
00090
00091
00092
00093
00094 bool failureReasonLoadedOk = loadFailureReason (bData, response);
00095 if (failureReasonLoadedOk)
00096 return bData->keys().size() == 1;
00097
00098
00099 bool intervalLoaded = loadInterval (bData, response);
00100 if (!intervalLoaded)
00101 return false;
00102
00103 bool peersLoaded = loadPeers (bData, response);
00104 if (!peersLoaded)
00105 return false;
00106
00107
00108 loadWarningMessage (bData, response);
00109 loadMinInterval (bData, response);
00110 loadComplete (bData, response);
00111 loadIncomplete (bData, response);
00112 loadTrackerId (bData, response);
00113
00114 return true;
00115 }
00116
00118
00132 bool TrackerResponseParser::loadFailureReason (const BDictionary *bData,
00133 TrackerResponse &response)
00134 {
00135 Q_ASSERT (bData != 0);
00136
00137 const BString *bFailureReason = dynamic_cast <const BString *>
00138 (bData->item (FailureReasonKeyName));
00139 if (!bFailureReason)
00140 return false;
00141
00142 response.d->failureReason = QString::fromUtf8 (bFailureReason->value());
00143 return true;
00144 }
00145
00147 bool TrackerResponseParser::loadWarningMessage (const BDictionary *bData,
00148 TrackerResponse &response)
00149 {
00150 Q_ASSERT (bData != 0);
00151
00152 const BString *bWarningMessage = dynamic_cast <const BString *>
00153 (bData->item (WarningMessageKeyName));
00154 if (!bWarningMessage)
00155 return false;
00156
00157 response.d->warningMessage = QString::fromUtf8 (bWarningMessage->value());
00158 return true;
00159 }
00160
00162 bool TrackerResponseParser::loadInterval (const BDictionary *bData,
00163 TrackerResponse &response)
00164 {
00165 Q_ASSERT (bData != 0);
00166
00167 const BInt *bInterval = dynamic_cast <const BInt *>
00168 (bData->item (IntervalKeyName));
00169 if (!bInterval || !isValidInterval (bInterval->value()))
00170 return false;
00171
00172
00173 response.d->interval = static_cast <uint> (bInterval->value());
00174 return true;
00175 }
00176
00178 bool TrackerResponseParser::loadMinInterval (const BDictionary *bData,
00179 TrackerResponse &response)
00180 {
00181 Q_ASSERT (bData != 0);
00182
00183 const BInt *bMinInterval = dynamic_cast <const BInt *>
00184 (bData->item (MinIntervalKeyName));
00185 if (!bMinInterval || !isValidInterval (bMinInterval->value()))
00186 return false;
00187
00188
00189 response.d->minInterval = static_cast <uint> (bMinInterval->value());
00190 return true;
00191 }
00192
00194 bool TrackerResponseParser::loadTrackerId (const BDictionary *bData,
00195 TrackerResponse &response)
00196 {
00197 Q_ASSERT (bData != 0);
00198
00199 const BString *bTrackerId = dynamic_cast <const BString *>
00200 (bData->item (TrackerIdKeyName));
00201 if (!bTrackerId)
00202 return false;
00203
00204 response.d->trackerId = bTrackerId->value();
00205 return true;
00206 }
00207
00209 bool TrackerResponseParser::loadComplete (const BDictionary *bData,
00210 TrackerResponse &response)
00211 {
00212 Q_ASSERT (bData != 0);
00213
00214 const BInt *bComplete = dynamic_cast <const BInt *>
00215 (bData->item (CompleteKeyName));
00216 if (!bComplete || !isValidNumberOfPeers (bComplete->value()))
00217 return false;
00218
00219
00220 response.d->complete = static_cast <uint> (bComplete->value());
00221 return true;
00222 }
00223
00225 bool TrackerResponseParser::loadIncomplete (const BDictionary *bData,
00226 TrackerResponse &response)
00227 {
00228 Q_ASSERT (bData != 0);
00229
00230 const BInt *bIncomplete = dynamic_cast <const BInt *>
00231 (bData->item (IncompleteKeyName));
00232 if (!bIncomplete || !isValidNumberOfPeers (bIncomplete->value()))
00233 return false;
00234
00235
00236 response.d->incomplete = static_cast <uint> (bIncomplete->value());
00237 return true;
00238 }
00239
00241 bool TrackerResponseParser::loadPeers (const BDictionary *bData,
00242 TrackerResponse &response)
00243 {
00244 Q_ASSERT (bData != 0);
00245
00246 TrackerResponse::PeerInfoList peerInfoList;
00247 bool peersLoaded = false;
00248 const BItem *bPeers = bData->item (PeersKeyName);
00249 if (dynamic_cast <const BString *> (bPeers) != 0) {
00250
00251 peersLoaded = loadPeersBinaryModel (
00252 static_cast <const BString *> (bPeers), peerInfoList);
00253 } else if (dynamic_cast <const BList *> (bPeers) != 0) {
00254
00255 peersLoaded = loadPeersDictionaryModel (
00256 static_cast <const BList *> (bPeers), peerInfoList);
00257 } else {
00258 return false;
00259 }
00260
00261 if (!peersLoaded)
00262 return false;
00263 response.d->peers = peerInfoList;
00264 return true;
00265 }
00266
00268 bool TrackerResponseParser::loadPeersBinaryModel (const BString *bPeers,
00269 TrackerResponse::PeerInfoList &peerInfoList)
00270 {
00271 Q_ASSERT (bPeers != 0);
00272
00273 QByteArray peers (bPeers->value());
00274 if ((peers.size() % OnePeerStringSizeBinaryModel) != 0)
00275 return false;
00276
00277 for (int peerIndex = 0; peerIndex < peers.size();
00278 peerIndex += OnePeerStringSizeBinaryModel) {
00279 peerInfoList.push_back (parseRawPeerInfo (
00280 peers.mid (peerIndex, OnePeerStringSizeBinaryModel)));
00281 }
00282
00283 return true;
00284 }
00285
00287 bool TrackerResponseParser::loadPeersDictionaryModel (const BList *bPeers,
00288 TrackerResponse::PeerInfoList &peerInfoList)
00289 {
00290 Q_ASSERT (bPeers != 0);
00291
00292
00293
00294 for (int i = 0; i < bPeers->size(); ++i) {
00295 const BDictionary *bPeerInfo = dynamic_cast <const BDictionary *>
00296 (bPeers->item (i));
00297 if (!bPeerInfo)
00298 return false;
00299
00300 PeerInfo peerInfo;
00301 bool peerInfoLoadedOk = loadPeerInfo (bPeerInfo, peerInfo);
00302 if (peerInfoLoadedOk)
00303 peerInfoList.push_back (peerInfo);
00304 }
00305
00306 return true;
00307 }
00308
00310 PeerInfo TrackerResponseParser::parseRawPeerInfo (const QByteArray &rawPeerInfo)
00311 {
00312 Q_ASSERT (rawPeerInfo.size() == OnePeerStringSizeBinaryModel);
00313
00314 BinaryReader reader (rawPeerInfo, BinaryReader::BigEndian);
00315
00316 QByteArray ipAddress;
00317 ipAddress += QByteArray::number (static_cast <uint> (reader.readByte()));
00318 ipAddress += '.';
00319 ipAddress += QByteArray::number (static_cast <uint> (reader.readByte()));
00320 ipAddress += '.';
00321 ipAddress += QByteArray::number (static_cast <uint> (reader.readByte()));
00322 ipAddress += '.';
00323 ipAddress += QByteArray::number (static_cast <uint> (reader.readByte()));
00324
00325 quint16 port = reader.readUInt16();
00326
00327 return PeerInfo (ipAddress, port, PeerInfo::PeerId());
00328 }
00329
00331 bool TrackerResponseParser::loadPeerInfo (const BDictionary *bPeerInfo,
00332 PeerInfo &peerInfo)
00333 {
00334 Q_ASSERT (bPeerInfo != 0);
00335
00336 PeerInfo::PeerId peerId;
00337 bool peerIdLoadedOk = loadPeerInfoPeerId (bPeerInfo, peerId);
00338 if (!peerIdLoadedOk)
00339 return false;
00340
00341 QByteArray hostAddress;
00342 bool hostAddressLoadedOk = loadPeerInfoHostAddress (bPeerInfo, hostAddress);
00343 if (!hostAddressLoadedOk)
00344 return false;
00345
00346 quint16 port;
00347 bool portLoadedOk = loadPeerInfoPort (bPeerInfo, port);
00348 if (!portLoadedOk)
00349 return false;
00350
00351 peerInfo = PeerInfo (hostAddress, port, peerId);
00352 return true;
00353 }
00354
00356 bool TrackerResponseParser::loadPeerInfoPeerId (const BDictionary *bPeerInfo,
00357 PeerInfo::PeerId &peerId)
00358 {
00359 Q_ASSERT (bPeerInfo != 0);
00360
00361 const BString *bPeerId = dynamic_cast <const BString *>
00362 (bPeerInfo->item (PeersPeerIdKeyName));
00363 if (!bPeerId)
00364 return false;
00365
00366 peerId = isValidPeerId (bPeerId->value()) ?
00367 PeerInfo::PeerId (bPeerId->value()) : PeerInfo::PeerId();
00368 return true;
00369 }
00370
00372 bool TrackerResponseParser::loadPeerInfoHostAddress (const BDictionary *bPeerInfo,
00373 QByteArray &hostAddress)
00374 {
00375 Q_ASSERT (bPeerInfo != 0);
00376
00377 const BString *bIpAddress = dynamic_cast <const BString *>
00378 (bPeerInfo->item (PeersIpKeyName));
00379 if (!bIpAddress)
00380 return false;
00381
00382 hostAddress = bIpAddress->value();
00383 return true;
00384 }
00385
00387 bool TrackerResponseParser::loadPeerInfoPort (const BDictionary *bPeerInfo,
00388 quint16 &port)
00389 {
00390 Q_ASSERT (bPeerInfo != 0);
00391
00392 const BInt *bPort = dynamic_cast <const BInt *>
00393 (bPeerInfo->item (PeersPortKeyName));
00394 if (!bPort)
00395 return false;
00396
00397 port = isValidPort (bPort->value()) ?
00398 static_cast <quint16> (bPort->value()) : 0;
00399 return true;
00400 }
00401
00403
00409 bool TrackerResponseParser::isValidInterval (qint64 interval)
00410 {
00411 return interval >= 0 && interval <= std::numeric_limits<uint>::max();
00412 }
00413
00415
00421 bool TrackerResponseParser::isValidNumberOfPeers (qint64 numOfPeers)
00422 {
00423 return numOfPeers >= 0 && numOfPeers <= std::numeric_limits<uint>::max();
00424 }
00425
00427
00431 bool TrackerResponseParser::isValidPeerId (const QByteArray &peerId)
00432 {
00433 return static_cast <uint> (peerId.size()) == PeerInfo::PeerId::size();
00434 }
00435
00437
00441 bool TrackerResponseParser::isValidPort (qint64 port)
00442 {
00443 return port >= 0 && port <= std::numeric_limits<quint16>::max();
00444 }
00445
00446
00447 const char *TrackerResponseParser::FailureReasonKeyName = "failure reason";
00448 const char *TrackerResponseParser::WarningMessageKeyName = "warning message";
00449 const char *TrackerResponseParser::IntervalKeyName = "interval";
00450 const char *TrackerResponseParser::MinIntervalKeyName = "min interval";
00451 const char *TrackerResponseParser::TrackerIdKeyName = "tracker id";
00452 const char *TrackerResponseParser::CompleteKeyName = "complete";
00453 const char *TrackerResponseParser::IncompleteKeyName = "incomplete";
00454 const char *TrackerResponseParser::PeersKeyName = "peers";
00455 const char *TrackerResponseParser::PeersPeerIdKeyName = "peer id";
00456 const char *TrackerResponseParser::PeersIpKeyName = "ip";
00457 const char *TrackerResponseParser::PeersPortKeyName = "port";
00458 const int TrackerResponseParser::OnePeerStringSizeBinaryModel = 6;