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 #ifndef PROTOCOLS__BIT_TORRENT__TRANSFERS__CHOKER_H 00024 #define PROTOCOLS__BIT_TORRENT__TRANSFERS__CHOKER_H 00025 00026 #include "Imports.h" 00027 #include "PacketProcessor.h" 00028 00029 namespace Protocols { 00030 namespace BitTorrent { 00031 namespace Transfers { 00032 00033 class Timer 00034 { 00035 CALITKO_MOCKABLE 00036 00037 public: 00038 virtual ~Timer() {} 00039 virtual void start (const Callable <void ()> &, qint64 timeout) = 0; 00040 virtual void stop() = 0; 00041 }; 00042 00043 class RandomNumberGenerator 00044 { 00045 CALITKO_MOCKABLE 00046 00047 public: 00048 virtual ~RandomNumberGenerator() {} 00049 virtual int random() = 0; 00050 }; 00051 00053 class TransferManagerState 00054 { 00055 CALITKO_MOCKABLE 00056 00057 public: 00058 virtual ~TransferManagerState() {} 00059 virtual bool isDownloading() const = 0; 00060 }; 00061 00063 00078 class Choker : public PacketProcessor 00079 { 00080 CALITKO_TESTABLE 00081 REFERENCE_OBJECT (Choker) 00082 00083 public: 00084 Choker (Timer *, 00085 RandomNumberGenerator *, 00086 TransferManagerState *); 00087 ~Choker(); 00088 00089 void start(); 00090 void stop(); 00091 00092 void chokingTime(); 00093 00094 // Interface PacketProcessor implementation: 00095 void openedSession (TransferSession *); 00096 void incomingPacket (TransferSession *, const Packet &); 00097 void outgoingPacket (TransferSession *, const Packet &); 00098 void closedSession (TransferSession *); 00099 00100 private: 00101 typedef QList <TransferSession *> Sessions; 00102 00103 void doOptimisticUnchokingIfTimeHasCome(); 00104 Choker::Sessions choseOptimisticlyUnchokedSessions(); 00105 void sortSessionsForSelection(); 00106 void reallocateUploadSlotsAndChokeUnchokeSessions(); 00107 int numberOfUploadSlots() const; 00108 static void chokeSessionIfNeeded (TransferSession *); 00109 static void unchokeSessionIfNeeded (TransferSession *); 00110 static bool moreDownloadedAndMoreInterested ( 00111 const TransferSession *, 00112 const TransferSession *); 00113 static bool moreUploadedAndMoreInterested ( 00114 const TransferSession *, 00115 const TransferSession *); 00116 00117 static const int UploadSlotsCount = 4; // \todo Change at runtime? 00118 static const int OptimisticChokingRate = 3; 00119 static const int ChokingTimeout = 10000; 00120 static const Choke choke; 00121 static const Unchoke unchoke; 00122 00123 Timer * timer; 00124 RandomNumberGenerator * randomNumberGenerator; 00125 TransferManagerState * transferManagerState; 00126 Sessions sessions; 00127 Sessions newSessions; 00128 Sessions optimisticlyUnchokedSessions; 00129 int optimisticChokingCounter; 00130 }; 00131 00132 } // namespace Transfers 00133 } // namespace BitTorrent 00134 } // namespace Protocols 00135 00136 #endif // PROTOCOLS__BIT_TORRENT__TRANSFERS__CHOKER_H