QrtReader.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2005-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #include "Qt.h"
00024 #include "QrtReader.h"
00025 #include "QueryRoutingTable.h"
00026 #include "Imports.cpp"
00027 
00028 using namespace Gnutella::PacketProcessing::QueryRouting;
00029 
00030 namespace Gnutella {
00031 namespace PacketProcessing {
00032 namespace QueryRouting {
00033 
00034 class QrtReaderPrivate
00035 {
00036     REFERENCE_OBJECT (QrtReaderPrivate)
00037 
00038 public:
00039     QueryRoutingTable       currentTable;
00040     bool                    isReset;
00041     bool                    isUpdating;
00042     quint8                  infinity;
00043     quint8                  entryBits;
00044     quint32                 tableSize;
00045     bool                    isCompressed;
00046     QByteArray              rawUpdateTable;
00047 
00048     QrtReaderPrivate() :    currentTable(), isReset (false), isUpdating (false),
00049                             infinity (0), entryBits (0), tableSize (0),
00050                             isCompressed (false), rawUpdateTable()
00051     {}
00052 };
00053 
00054 } // QueryRouting
00055 } // PacketProcessing
00056 } // Gnutella
00057 
00058 const QueryRoutingTable & QrtReader::currentTable() const
00059 { return p->currentTable; }
00060 
00061 QrtReader::QrtReader()
00062  :  p (new QrtReaderPrivate)
00063 {
00064     p->currentTable.reset (8);
00065     p->isUpdating = false;
00066 }
00067 
00068 QrtReader::~QrtReader()
00069 {
00070     delete p;
00071 }
00072 
00073 bool QrtReader::handlePacket (const Packet &packet)
00074 {
00075     using namespace Gnutella::Packets;
00076     if (packet.payloadDescriptor() != QueryRoutingDescriptor)
00077         return false;
00078     const Packets::QueryRouting &qrp = Packets::QueryRouting::castFrom (packet);
00079     switch (qrp.variant())
00080     {
00081     case Packets::QueryRouting::ResetVariant:
00082         processReset (QueryRoutingReset::castFrom (packet));
00083         break;
00084     case Packets::QueryRouting::PatchVariant:
00085         processPatch (QueryRoutingPatch::castFrom (packet));
00086         break;
00087     case Packets::QueryRouting::UnknownVariant:
00088     default:
00089         break;
00090     }
00091     return true;
00092 }
00093 
00094 void QrtReader::processReset (const QueryRoutingReset &reset)
00095 {
00096     p->isReset = true;
00097     p->tableSize = reset.tableLength();
00098     p->infinity = reset.infinity();
00099 
00101 
00108 }
00109 
00110 void QrtReader::processPatch (const QueryRoutingPatch &patch)
00111 {
00112     if (patch.seqNo() == 1) {
00113         p->isUpdating = true;
00114         p->rawUpdateTable.resize (0);
00115         p->entryBits = patch.entryBits();
00116         p->isCompressed = patch.compressor() == QueryRoutingPatch::ZLIB;
00118 
00120     }
00121 
00123     p->rawUpdateTable.append (patch.data());
00124 
00125     if (patch.seqNo() == patch.seqSize())
00126         completeTableUpdate();
00127 }
00128 
00129 void QrtReader::completeTableUpdate()
00130 {
00131     if (p->isCompressed)
00132         p->rawUpdateTable = unCompress (p->rawUpdateTable);
00133 
00134     // Check whether the received patch matches the expected values.
00135     if (p->rawUpdateTable.size() * 8 != qint32 (p->entryBits * p->tableSize)) {
00137         return;
00138     }
00139 
00140     if (p->isReset) {
00141         p->currentTable.reset (p->tableSize);
00142     }
00143     if (p->tableSize != p->currentTable.size()) {
00145         return;
00146     }
00147     p->currentTable.applyPatch (p->rawUpdateTable, p->entryBits);
00148 
00149     emit qrtRead();
00150 
00151     p->isReset = false;
00152     p->isUpdating = false;
00153     p->rawUpdateTable.resize (0);
00154 }