TransferSessionImpl.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2006-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 "TransferSessionImpl.h"
00025 #include "Imports.cpp"
00026 
00028 
00039 TransferSessionImpl::TransferSessionImpl (
00040         Session *session,
00041         const Handshake &handshake,
00042         IntegerResetStopwatch *downloadStopwatch,
00043         IntegerResetStopwatch *uploadStopwatch,
00044         TransferSessionStatus *status)
00045  :  session_ (session), handshake_ (handshake), status_ (status),
00046     inPacketDispatcher_(), outPacketDispatcher_(),
00047     areWeChoked_ (true), areWeInterested_ (false), areWeSeeder_ (false),
00048     isPeerChoked_ (true), isPeerInterested_ (false), isPeerSeeder_ (false),
00049     totalDownloaded_ (0), totalUploaded_ (0),
00050     downloadStopwatch_ (downloadStopwatch), uploadStopwatch_ (uploadStopwatch),
00051     downloadHistory_(), uploadHistory_(),
00052     peerPiecesAvailable_ (handshake.numberPieces),
00053     wePiecesAvailable_ (handshake.numberPieces)
00054 {
00055     inPacketDispatcher_.registerTypeHandler (
00056         Callable <void (const Choke &)> (
00057             this, &TransferSessionImpl::receivedChoke));
00058     inPacketDispatcher_.registerTypeHandler (
00059         Callable <void (const Unchoke &)> (
00060             this, &TransferSessionImpl::receivedUnchoke));
00061     inPacketDispatcher_.registerTypeHandler (
00062         Callable <void (const Interested &)> (
00063             this, &TransferSessionImpl::receivedInterested));
00064     inPacketDispatcher_.registerTypeHandler (
00065         Callable <void (const NotInterested &)> (
00066             this, &TransferSessionImpl::receivedNotInterested));
00067     inPacketDispatcher_.registerTypeHandler (
00068         Callable <void (const Piece &)> (
00069             this, &TransferSessionImpl::receivedPiece));
00070     inPacketDispatcher_.registerTypeHandler (
00071         Callable <void (const BitField &)> (
00072             this, &TransferSessionImpl::receivedBitField));
00073     inPacketDispatcher_.registerTypeHandler (
00074         Callable <void (const Have &)> (
00075             this, &TransferSessionImpl::receivedHave));
00076     if (handshake_.hasFastExtension) {
00077         inPacketDispatcher_.registerTypeHandler (
00078             Callable <void (const HaveAll &)> (
00079                 this, &TransferSessionImpl::receivedHaveAll));
00080         inPacketDispatcher_.registerTypeHandler (
00081             Callable <void (const HaveNone &)> (
00082                 this, &TransferSessionImpl::receivedHaveNone));
00083     }
00084     inPacketDispatcher_.registerNotHandledHandler (
00085         Callable <void (const PacketBase &)> (
00086             this, &TransferSessionImpl::receivedUnhandled));
00087 
00088     outPacketDispatcher_.registerTypeHandler (
00089         Callable <void (const Choke &)> (
00090             this, &TransferSessionImpl::sentChoke));
00091     outPacketDispatcher_.registerTypeHandler (
00092         Callable <void (const Unchoke &)> (
00093             this, &TransferSessionImpl::sentUnchoke));
00094     outPacketDispatcher_.registerTypeHandler (
00095         Callable <void (const Interested &)> (
00096             this, &TransferSessionImpl::sentInterested));
00097     outPacketDispatcher_.registerTypeHandler (
00098         Callable <void (const NotInterested &)> (
00099             this, &TransferSessionImpl::sentNotInterested));
00100     outPacketDispatcher_.registerTypeHandler (
00101         Callable <void (const Piece &)> (
00102             this, &TransferSessionImpl::sentPiece));
00103     outPacketDispatcher_.registerTypeHandler (
00104         Callable <void (const BitField &)> (
00105             this, &TransferSessionImpl::sentBitField));
00106     outPacketDispatcher_.registerTypeHandler (
00107         Callable <void (const Have &)> (
00108             this, &TransferSessionImpl::sentHave));
00109     if (handshake_.hasFastExtension) {
00110         outPacketDispatcher_.registerTypeHandler (
00111             Callable <void (const HaveAll &)> (
00112                 this, &TransferSessionImpl::sentHaveAll));
00113         outPacketDispatcher_.registerTypeHandler (
00114             Callable <void (const HaveNone &)> (
00115                 this, &TransferSessionImpl::sentHaveNone));
00116     }
00117     outPacketDispatcher_.registerNotHandledHandler (
00118         Callable <void (const PacketBase &)> (
00119             this, &TransferSessionImpl::sentUnhandled));
00120 
00121     for (int i = SpeedMovingAverageDuration; i > 0; --i) {
00122         downloadHistory_.append (0);
00123         uploadHistory_.append (0);
00124     }
00125 }
00126 
00128 
00131 void TransferSessionImpl::sendPacket (const Packet &packet)
00132 {
00133     status_->transferSessionSendingPacket (this, packet);
00134     outPacketDispatcher_.dispatch (*packet);
00135     session_->send (packet);
00136 }
00137 
00139 void TransferSessionImpl::close()
00140 {
00141     session_->close();
00142 }
00143 
00145 bool TransferSessionImpl::areWeChoked() const
00146 {
00147     return areWeChoked_;
00148 }
00149 
00151 bool TransferSessionImpl::areWeInterested() const
00152 {
00153     return areWeInterested_;
00154 }
00155 
00157 bool TransferSessionImpl::areWeSnubbed() const
00158 {
00159     return downloadStopwatch_->elapsedSeconds() > SnubbedTimeout
00160             && !isPeerChoked();
00161 }
00162 
00164 bool TransferSessionImpl::areWeSeeder() const
00165 {
00166     return areWeSeeder_;
00167 }
00168 
00170 bool TransferSessionImpl::isPeerChoked() const
00171 {
00172     return isPeerChoked_;
00173 }
00174 
00176 bool TransferSessionImpl::isPeerInterested() const
00177 {
00178     return isPeerInterested_;
00179 }
00180 
00182 bool TransferSessionImpl::isPeerSnubbed() const
00183 {
00184     return uploadStopwatch_->elapsedSeconds() > SnubbedTimeout
00185             && !areWeChoked();
00186 }
00187 
00189 bool TransferSessionImpl::isPeerSeeder() const
00190 {
00191     return isPeerSeeder_;
00192 }
00193 
00195 qint64 TransferSessionImpl::totalDownloaded() const
00196 {
00197     return totalDownloaded_;
00198 }
00199 
00201 qint64 TransferSessionImpl::totalUploaded() const
00202 {
00203     return totalUploaded_;
00204 }
00205 
00207 qint64 TransferSessionImpl::currentDownloadSpeed() const
00208 {
00209     updateDownloadSpeed (0);
00210     return calculateAverage (downloadHistory_);
00211 }
00212 
00214 qint64 TransferSessionImpl::currentUploadSpeed() const
00215 {
00216     updateUploadSpeed (0);
00217     return calculateAverage (uploadHistory_);
00218 }
00219 
00221 QBitArray TransferSessionImpl::peerPiecesAvailable() const
00222 {
00223     return peerPiecesAvailable_;
00224 }
00225 
00227 QBitArray TransferSessionImpl::wePiecesAvailable() const
00228 {
00229     return wePiecesAvailable_;
00230 }
00231 
00233 
00241 void TransferSessionImpl::sessionReceivedData (Session *, const Data &data)
00242 {
00243     Packet packet = data;
00244     if (inPacketDispatcher_.dispatch (*packet))
00245         status_->transferSessionReceivedPacket (this, packet);
00246 }
00247 
00249 
00253 void TransferSessionImpl::sessionSendingData (Session *, const Data &)
00254 {
00255     // Nothing to do here.
00256 }
00257 
00259 
00262 void TransferSessionImpl::sessionClosing (Session *)
00263 {
00264     status_->transferSessionClosing (this);
00265 }
00266 
00268 
00271 void TransferSessionImpl::sessionClosed (Session *)
00272 {
00273     status_->transferSessionClosed (this);
00274 }
00275 
00277 void TransferSessionImpl::receivedChoke (const Choke &)
00278 {
00279     areWeChoked_ = true;
00280 }
00281 
00283 void TransferSessionImpl::receivedUnchoke (const Unchoke &)
00284 {
00285     areWeChoked_ = false;
00286 }
00287 
00289 void TransferSessionImpl::receivedInterested (const Interested &)
00290 {
00291     isPeerInterested_ = true;
00292 }
00293 
00295 void TransferSessionImpl::receivedNotInterested (const NotInterested &)
00296 {
00297     isPeerInterested_ = false;
00298 }
00299 
00301 void TransferSessionImpl::receivedPiece (const Piece &piece)
00302 {
00303     int length = piece.pieceBytes().length();
00304     totalDownloaded_ += length;
00305     updateDownloadSpeed (length);
00306 }
00307 
00309 void TransferSessionImpl::receivedBitField (const BitField &bitField)
00310 {
00311     setPiecesAvailable (peerPiecesAvailable_, bitField.bitField());
00312     unregisterBitFieldHaveAllHaveNoneReceiveHandlers();
00313 }
00314 
00316 void TransferSessionImpl::receivedHaveAll (const HaveAll &)
00317 {
00318     peerPiecesAvailable_.fill (true);
00319     isPeerSeeder_ = true;
00320     unregisterBitFieldHaveAllHaveNoneReceiveHandlers();
00321 }
00322 
00324 void TransferSessionImpl::receivedHaveNone (const HaveNone &)
00325 {
00326     peerPiecesAvailable_.fill (false);
00327     isPeerSeeder_ = false;
00328     unregisterBitFieldHaveAllHaveNoneReceiveHandlers();
00329 }
00330 
00332 void TransferSessionImpl::receivedHave (const Have &have)
00333 {
00334     peerPiecesAvailable_.setBit (have.pieceIndex(), true);
00335     if (peerPiecesAvailable_.size() == peerPiecesAvailable_.count (true))
00336         isPeerSeeder_ = true;
00337 }
00338 
00340 
00346 void TransferSessionImpl::receivedUnhandled (const PacketBase &)
00347 {
00348     session_->close(); // It is not allowed to send this type of packet.
00349 }
00350 
00352 void TransferSessionImpl::sentChoke (const Choke &)
00353 {
00354     isPeerChoked_ = true;
00355 }
00356 
00358 void TransferSessionImpl::sentUnchoke (const Unchoke &)
00359 {
00360     isPeerChoked_ = false;
00361 }
00362 
00364 void TransferSessionImpl::sentInterested (const Interested &)
00365 {
00366     areWeInterested_ = true;
00367 }
00368 
00370 void TransferSessionImpl::sentNotInterested (const NotInterested &)
00371 {
00372     areWeInterested_ = false;
00373 }
00374 
00376 void TransferSessionImpl::sentPiece (const Piece &piece)
00377 {
00378     int length = piece.pieceBytes().length();
00379     totalUploaded_ += length;
00380     updateUploadSpeed (length);
00381 }
00382 
00384 void TransferSessionImpl::sentBitField (const BitField &bitField)
00385 {
00386     setPiecesAvailable (wePiecesAvailable_, bitField.bitField());
00387     unregisterBitFieldHaveAllHaveNoneSendHandlers();
00388 }
00389 
00391 void TransferSessionImpl::sentHaveAll (const HaveAll &)
00392 {
00393     wePiecesAvailable_.fill (true);
00394     areWeSeeder_ = true;
00395     unregisterBitFieldHaveAllHaveNoneSendHandlers();
00396 }
00397 
00399 void TransferSessionImpl::sentHaveNone (const HaveNone &)
00400 {
00401     wePiecesAvailable_.fill (false);
00402     areWeSeeder_ = false;
00403     unregisterBitFieldHaveAllHaveNoneSendHandlers();
00404 }
00405 
00407 void TransferSessionImpl::sentHave (const Have &have)
00408 {
00409     wePiecesAvailable_.setBit (have.pieceIndex(), true);
00410     if (wePiecesAvailable_.size() == wePiecesAvailable_.count (true))
00411         areWeSeeder_ = true;
00412 }
00413 
00415 
00421 void TransferSessionImpl::sentUnhandled (const PacketBase &)
00422 {
00423     Q_ASSERT (false); // It is not allowed to send this packet type!
00424 }
00425 
00427 
00434 void TransferSessionImpl::updateDownloadSpeed (int pieceLength) const
00435 {
00436     qint64 delay = downloadStopwatch_->elapsedSeconds();
00437     shiftList (downloadHistory_, delay);
00438     downloadHistory_.front() += pieceLength;
00439     downloadStopwatch_->reset();
00440 }
00441 
00443 
00450 void TransferSessionImpl::updateUploadSpeed (int pieceLength) const
00451 {
00452     qint64 delay = uploadStopwatch_->elapsedSeconds();
00453     shiftList (uploadHistory_, delay);
00454     uploadHistory_.front() += pieceLength;
00455     uploadStopwatch_->reset();
00456 }
00457 
00459 void TransferSessionImpl::shiftList (QList <qint64> &list, qint64 count)
00460 {
00461     count = qMin (count, static_cast <qint64> (SpeedMovingAverageDuration));
00462     for (qint64 i = count; i > 0; --i) {
00463         list.prepend (0);
00464         list.takeLast();
00465     }
00466 }
00467 
00469 qint64 TransferSessionImpl::calculateAverage (const QList <qint64> &list)
00470 {
00471     Q_ASSERT (list.size() != 0);
00472     qint64 sum = std::accumulate (list.begin(), list.end(), 0);
00473     return sum / list.size();
00474 }
00475 
00477 void TransferSessionImpl::setPiecesAvailable (QBitArray &piecesAvailable,
00478                                               const QByteArray &bitField)
00479 {
00480     int index = 0;
00481     int last = piecesAvailable.size();
00482     foreach (const char &ch, bitField)
00483         for (uchar mask = 0x80; mask != 0 && index < last; mask >>= 1, ++index)
00484             piecesAvailable.setBit (index, ch & mask);
00485 }
00486 
00488 
00500 void TransferSessionImpl::unregisterBitFieldHaveAllHaveNoneReceiveHandlers()
00501 {
00502     inPacketDispatcher_.unregisterTypeHandler (
00503         Callable <void (const BitField &)> (
00504             this, &TransferSessionImpl::receivedBitField));
00505     inPacketDispatcher_.unregisterTypeHandler (
00506         Callable <void (const HaveAll &)> (
00507             this, &TransferSessionImpl::receivedHaveAll));
00508     inPacketDispatcher_.unregisterTypeHandler (
00509         Callable <void (const HaveNone &)> (
00510             this, &TransferSessionImpl::receivedHaveNone));
00511 }
00512 
00514 
00519 void TransferSessionImpl::unregisterBitFieldHaveAllHaveNoneSendHandlers()
00520 {
00521     outPacketDispatcher_.unregisterTypeHandler (
00522         Callable <void (const BitField &)> (
00523             this, &TransferSessionImpl::sentBitField));
00524     outPacketDispatcher_.unregisterTypeHandler (
00525         Callable <void (const HaveAll &)> (
00526             this, &TransferSessionImpl::sentHaveAll));
00527     outPacketDispatcher_.unregisterTypeHandler (
00528         Callable <void (const HaveNone &)> (
00529             this, &TransferSessionImpl::sentHaveNone));
00530 }