mirror of https://github.com/aria2/aria2
2006-11-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
To divide TorrentMan into 6 classes: BtContext, BtRuntime, PeerStorage, PieceStorage, BtAnnounce and BtProgressInfoFile * src/TrackerWatcherComand.h: Made subclass of BtContextAwareCommand. * src/SeedCheckCommand.cc: Use pieceStorage, btRuntime * src/PeerAbstractCommand.h: Made subclass of BtContextAwareCommand. * src/PeerAbstractCommand.cc: Use btRuntime. * src/BtContextAwareCommand.h: New class. * src/FileEntry.h: Added accessor methods for following variables. (path): Made private. (length): Made private. (offset): Made private. (extracted): Made private. (requested): Made private. (FileEntries): New definition. (FileEntryHandle): New definition. * src/FileEntry.cc: New file. * src/HaveEraseCommand.h: Made subclass of BtContextAwareCommand. * src/HaveEraseCommand.cc: Use btRuntime, pieceStorage. * src/PeerChokeCommand.h: Made subclass of BtContextAwareCommand. * src/PeerChokeCommand.cc: Use btRuntime, peerStorage, pieceStorage. * src/PieceStorage.h: New file. * src/PeerInteractionCommand.h: Use btContext. * src/PeerInteractionCommand.cc: Use pieceStorage, peerStorage, btRuntime. * src/DefaultBtProgressInfoFile.h: New file. * src/DefaultBtProgressInfoFile.cc: New file. * src/File.cc (Util.h): New include. (mkdirs): New function. * src/MultiDiskAdaptor.h (mkdir): New function. * src/PeerListProcessor.h (Peers): Removed. * src/PeerInteraction.h (torrentMan): Removed. (btContext): New variable. (peerStorage): New variable. (pieceStorage): New variable. (btAnnounce): New variable. (getTorrentMan): Removed. (getBtContext): New function. * src/PeerInteraction.cc: Use btContext, peerStorage, pieceStorage, btAnnounce. * src/HandshakeMessage.h (TorrentMan.h): Removed. * src/HandshakeMessage.cc: Use btContext. * src/DefaultBtAnnounce.cc: New file. * src/MultiDiskWriter.cc: Use the accessor methods of FileEntry. * src/DefaultPieceStorage.cc: New file. * src/DefaultBtContext.h: New file. * src/TorrentRequestInfo.cc: Use btContext, pieceStorage. Use the accessor methods of FileEntry. * src/CookieBox.cc: Updated to use Util::slice(). * src/PieceMessage.cc: Use btContext, pieceStorage. * src/common.h (SharedHandle.h): New include. * src/PeerMessage.cc (PeerMessage): Added btContext, peerStorage, pieceStorage. * src/TorrentAutoSaveCommand.h: Made subclass of BtContextAwareCommand. * src/DiskAdaptor.h (topDir): Removed. (getFileEntryFromPath): Changed the return type to FileEntryHandle. (setTopDir): Removed. (getTopDir): Removed. * src/BtContext.h: New file. * src/DefaultPeerStorage.h: New file. * src/PieceMessage.h (TorrentMan.h): Removed. * src/RequestMessage.h (TorrentMan.h): Removed. * src/TorrentDownloadEngine.h (uploadLength): New variable. (btContext): New variable. (btRuntime): New variable. (pieceStorage): New variable. (peerStorage): New variable. (btAnnounce): New variable. (btProgressInfoFile): New variable. (torrentMan): Removed. (setBtContext): New function. * src/TorrentDownloadEngine.cc: Use BtContext, BtRuntime, pieceStorage, peerStorage, btAnnounce, btProgressInfoFile. * src/Piece.h (toString): New function. (Pieces): New type definition. * src/Peer.h (active): New variable. (Peer): Added active. (activate): Set active to true. (deactivate): Set active to false. (isActive): New function. (Peers): New type definition. * src/DirectDiskAdaptor.cc (getFilePath): Use the accessor methods of FileEntry. * src/TorrentConsoleDownloadEngine.h (afterEachIteration): New function. * src/TorrentConsoleDownloadEngine.cc (haltRequested): New variable. (sendStatistics): Use pieceStorage, btRuntime. (afterEachIteration): New function. * src/AnnounceList: AnnounceTier->AnnounceTierHandle. * src/Directry.h (Directory): New function. (DirectoryHandle): New type definition. * src/BtProgressInfoFile.h: New file. * src/RequestMessage.cc: Use pieceStorage. * src/BtRuntime.h: New file. * src/DefaultBtContext.cc: New file. * src/BitfieldMan.h (getCompletedLength): New function(private). (getCompletedLength): New function. (getFilteredCompletedLength): New function. * src/BitfieldMan.h (getCompletedLength): New function(private). (getCompletedLength): New function. (getFilteredCompletedLength): New function. * src/MultiDiskAdaptor.cc (mkdir): New function. (openFile): Call mkdir(). (initAndOpenFile): Call mkdir(). * src/CancelMessage.h (TorrentMan.h): Removed. * src/RejectMessage.h (TorrentMan.h): Removed. * src/DownloadEngineFactory.cc (DefaultPieceStorage.h): New include. (DefaultPeerStorage.h): New include. (DefaultBtAnnounce.h): New include. (DefaultBtProgressInfoFile.h): New include. (newTorrentConsoleEngine): Rewritten. * src/ShareRatioSeedCriteria.h (torrentMan): Removed. (btContext): New variable. (peerStorage): New variable. (btRuntime): New variable. (evaluate): Use btContext, btRuntime, peerStorage. * src/AnnounceTier.h: New file. * src/BtAnnounce.h: New file. * src/BtRegistry.h: New file. * src/PeerInitiateConnectionCommand.h: Added btContext. * src/PeerConnection.h (TorrentMan.h): Removed. * src/PeerMessageFactory.cc: Use btContext, pieceStorage. * src/Util.h (slice): Added an argument. * src/Util.cc (slice): Added an argument to control whether trim is made or not. * src/PeerStorage.h: New file. * src/BtRegistry.cc: New file. * src/TrackerUpdateCommand.h: Made subclass of BtContextAwareCommand. * src/CopyDiskAdaptor.cc: Use the accessor methods of FileEntry. * src/MultiDiskWriter.h: FileEntry -> FileEntryHandle * src/PeerListenCommand.cc: Use btRuntime, peerStorage, btContext. * src/TorrentRequestInfo.h (e): Removed. (showFileEntry): Added an argument. (getDownloadEngine): Return 0. * src/DefaultBtAnnounce.h: New file. * src/TorrentAutoSaveCommand.cc: Use btRuntime, btProgressInfoFile. * src/TrackerWatcherComand.cc: Use btRuntime, btAnnounce, * src/PeerMessageFactory.h (btContext): New variable. (pieceStorage): New variable. * src/TrackerUpdateCommand.cc: Use btRuntime, peerStorage, btContext, btAnnounce. * src/DiskAdaptor.cc (DiskAdaptor): Removed topDir. (~DiskAdaptor): Removed topDir. * src/PeerListenCommand.h: Made subclass of BtContextAwareCommand. * src/SeedCheckCommand.h: Made subclass of BtContextAwareCommand. * src/File.h (mkdirs): New function. * src/DefaultPeerStorage): New file. * src/DownloadEngineFactory.h (newTorrentConsoleEngine): Use btContext. * src/BtContextAwareCommand.cc: New file. * src/PeerInitiateConnectionCommand.cc: Use btRuntime, peerStorage. * src/PeerMessage.h (btContext): New variable. (peerStorage): New variable. (pieceStorage): New variable. (setBtContext): New function. * src/Directry.cc (Directory): New function. (createDir): Do nothing if name.size() == 0. * src/AnnounceList.h (AnnounceTier): Removed. (AnnounceTiers): Removed. * src/DefaultPieceStorage.h: New file. * src/Piece.cc (toString): New function. To fix typo: * src/main.cc (showVersion): Fixed typo. To fix compile warning: * src/DelegatingPeerListProcessor.cc (canHandle): Added "return false".pull/1/head
parent
b8737b0e7c
commit
ec642ad294
198
ChangeLog
198
ChangeLog
|
@ -1,3 +1,201 @@
|
|||
2006-11-05 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
To divide TorrentMan into 6 classes: BtContext, BtRuntime,
|
||||
PeerStorage, PieceStorage, BtAnnounce and BtProgressInfoFile
|
||||
|
||||
* src/TrackerWatcherComand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/SeedCheckCommand.cc: Use pieceStorage, btRuntime
|
||||
* src/PeerAbstractCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/PeerAbstractCommand.cc: Use btRuntime.
|
||||
* src/BtContextAwareCommand.h: New class.
|
||||
* src/FileEntry.h: Added accessor methods for following variables.
|
||||
(path): Made private.
|
||||
(length): Made private.
|
||||
(offset): Made private.
|
||||
(extracted): Made private.
|
||||
(requested): Made private.
|
||||
(FileEntries): New definition.
|
||||
(FileEntryHandle): New definition.
|
||||
* src/FileEntry.cc: New file.
|
||||
* src/HaveEraseCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/HaveEraseCommand.cc: Use btRuntime, pieceStorage.
|
||||
* src/PeerChokeCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/PeerChokeCommand.cc: Use btRuntime, peerStorage, pieceStorage.
|
||||
* src/PieceStorage.h: New file.
|
||||
* src/PeerInteractionCommand.h: Use btContext.
|
||||
* src/PeerInteractionCommand.cc: Use pieceStorage, peerStorage,
|
||||
btRuntime.
|
||||
* src/DefaultBtProgressInfoFile.h: New file.
|
||||
* src/DefaultBtProgressInfoFile.cc: New file.
|
||||
* src/File.cc
|
||||
(Util.h): New include.
|
||||
(mkdirs): New function.
|
||||
* src/MultiDiskAdaptor.h
|
||||
(mkdir): New function.
|
||||
* src/PeerListProcessor.h
|
||||
(Peers): Removed.
|
||||
* src/PeerInteraction.h
|
||||
(torrentMan): Removed.
|
||||
(btContext): New variable.
|
||||
(peerStorage): New variable.
|
||||
(pieceStorage): New variable.
|
||||
(btAnnounce): New variable.
|
||||
(getTorrentMan): Removed.
|
||||
(getBtContext): New function.
|
||||
* src/PeerInteraction.cc: Use btContext, peerStorage, pieceStorage,
|
||||
btAnnounce.
|
||||
* src/HandshakeMessage.h
|
||||
(TorrentMan.h): Removed.
|
||||
* src/HandshakeMessage.cc: Use btContext.
|
||||
* src/DefaultBtAnnounce.cc: New file.
|
||||
* src/MultiDiskWriter.cc: Use the accessor methods of FileEntry.
|
||||
* src/DefaultPieceStorage.cc: New file.
|
||||
* src/DefaultBtContext.h: New file.
|
||||
* src/TorrentRequestInfo.cc: Use btContext, pieceStorage.
|
||||
Use the accessor methods of FileEntry.
|
||||
* src/CookieBox.cc: Updated to use Util::slice().
|
||||
* src/PieceMessage.cc: Use btContext, pieceStorage.
|
||||
* src/common.h (SharedHandle.h): New include.
|
||||
* src/PeerMessage.cc (PeerMessage): Added btContext, peerStorage,
|
||||
pieceStorage.
|
||||
* src/TorrentAutoSaveCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/DiskAdaptor.h
|
||||
(topDir): Removed.
|
||||
(getFileEntryFromPath): Changed the return type to FileEntryHandle.
|
||||
(setTopDir): Removed.
|
||||
(getTopDir): Removed.
|
||||
* src/BtContext.h: New file.
|
||||
* src/DefaultPeerStorage.h: New file.
|
||||
* src/PieceMessage.h (TorrentMan.h): Removed.
|
||||
* src/RequestMessage.h (TorrentMan.h): Removed.
|
||||
* src/TorrentDownloadEngine.h
|
||||
(uploadLength): New variable.
|
||||
(btContext): New variable.
|
||||
(btRuntime): New variable.
|
||||
(pieceStorage): New variable.
|
||||
(peerStorage): New variable.
|
||||
(btAnnounce): New variable.
|
||||
(btProgressInfoFile): New variable.
|
||||
(torrentMan): Removed.
|
||||
(setBtContext): New function.
|
||||
* src/TorrentDownloadEngine.cc: Use BtContext, BtRuntime, pieceStorage,
|
||||
peerStorage, btAnnounce, btProgressInfoFile.
|
||||
* src/Piece.h
|
||||
(toString): New function.
|
||||
(Pieces): New type definition.
|
||||
* src/Peer.h
|
||||
(active): New variable.
|
||||
(Peer): Added active.
|
||||
(activate): Set active to true.
|
||||
(deactivate): Set active to false.
|
||||
(isActive): New function.
|
||||
(Peers): New type definition.
|
||||
* src/DirectDiskAdaptor.cc
|
||||
(getFilePath): Use the accessor methods of FileEntry.
|
||||
* src/TorrentConsoleDownloadEngine.h
|
||||
(afterEachIteration): New function.
|
||||
* src/TorrentConsoleDownloadEngine.cc
|
||||
(haltRequested): New variable.
|
||||
(sendStatistics): Use pieceStorage, btRuntime.
|
||||
(afterEachIteration): New function.
|
||||
* src/AnnounceList: AnnounceTier->AnnounceTierHandle.
|
||||
* src/Directry.h
|
||||
(Directory): New function.
|
||||
(DirectoryHandle): New type definition.
|
||||
* src/BtProgressInfoFile.h: New file.
|
||||
* src/RequestMessage.cc: Use pieceStorage.
|
||||
* src/BtRuntime.h: New file.
|
||||
* src/DefaultBtContext.cc: New file.
|
||||
* src/BitfieldMan.h
|
||||
(getCompletedLength): New function(private).
|
||||
(getCompletedLength): New function.
|
||||
(getFilteredCompletedLength): New function.
|
||||
* src/BitfieldMan.h
|
||||
(getCompletedLength): New function(private).
|
||||
(getCompletedLength): New function.
|
||||
(getFilteredCompletedLength): New function.
|
||||
* src/MultiDiskAdaptor.cc
|
||||
(mkdir): New function.
|
||||
(openFile): Call mkdir().
|
||||
(initAndOpenFile): Call mkdir().
|
||||
* src/CancelMessage.h
|
||||
(TorrentMan.h): Removed.
|
||||
* src/RejectMessage.h
|
||||
(TorrentMan.h): Removed.
|
||||
* src/DownloadEngineFactory.cc
|
||||
(DefaultPieceStorage.h): New include.
|
||||
(DefaultPeerStorage.h): New include.
|
||||
(DefaultBtAnnounce.h): New include.
|
||||
(DefaultBtProgressInfoFile.h): New include.
|
||||
(newTorrentConsoleEngine): Rewritten.
|
||||
* src/ShareRatioSeedCriteria.h
|
||||
(torrentMan): Removed.
|
||||
(btContext): New variable.
|
||||
(peerStorage): New variable.
|
||||
(btRuntime): New variable.
|
||||
(evaluate): Use btContext, btRuntime, peerStorage.
|
||||
* src/AnnounceTier.h: New file.
|
||||
* src/BtAnnounce.h: New file.
|
||||
* src/BtRegistry.h: New file.
|
||||
* src/PeerInitiateConnectionCommand.h: Added btContext.
|
||||
* src/PeerConnection.h (TorrentMan.h): Removed.
|
||||
* src/PeerMessageFactory.cc: Use btContext, pieceStorage.
|
||||
* src/Util.h
|
||||
(slice): Added an argument.
|
||||
* src/Util.cc
|
||||
(slice): Added an argument to control whether trim is made or not.
|
||||
* src/PeerStorage.h: New file.
|
||||
* src/BtRegistry.cc: New file.
|
||||
* src/TrackerUpdateCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/CopyDiskAdaptor.cc: Use the accessor methods of FileEntry.
|
||||
* src/MultiDiskWriter.h: FileEntry -> FileEntryHandle
|
||||
* src/PeerListenCommand.cc: Use btRuntime, peerStorage, btContext.
|
||||
* src/TorrentRequestInfo.h
|
||||
(e): Removed.
|
||||
(showFileEntry): Added an argument.
|
||||
(getDownloadEngine): Return 0.
|
||||
* src/DefaultBtAnnounce.h: New file.
|
||||
* src/TorrentAutoSaveCommand.cc: Use btRuntime, btProgressInfoFile.
|
||||
* src/TrackerWatcherComand.cc: Use btRuntime, btAnnounce,
|
||||
* src/PeerMessageFactory.h
|
||||
(btContext): New variable.
|
||||
(pieceStorage): New variable.
|
||||
* src/TrackerUpdateCommand.cc: Use btRuntime, peerStorage, btContext,
|
||||
btAnnounce.
|
||||
* src/DiskAdaptor.cc
|
||||
(DiskAdaptor): Removed topDir.
|
||||
(~DiskAdaptor): Removed topDir.
|
||||
* src/PeerListenCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/SeedCheckCommand.h: Made subclass of BtContextAwareCommand.
|
||||
* src/File.h (mkdirs): New function.
|
||||
* src/DefaultPeerStorage): New file.
|
||||
* src/DownloadEngineFactory.h
|
||||
(newTorrentConsoleEngine): Use btContext.
|
||||
* src/BtContextAwareCommand.cc: New file.
|
||||
* src/PeerInitiateConnectionCommand.cc: Use btRuntime, peerStorage.
|
||||
* src/PeerMessage.h
|
||||
(btContext): New variable.
|
||||
(peerStorage): New variable.
|
||||
(pieceStorage): New variable.
|
||||
(setBtContext): New function.
|
||||
* src/Directry.cc
|
||||
(Directory): New function.
|
||||
(createDir): Do nothing if name.size() == 0.
|
||||
* src/AnnounceList.h
|
||||
(AnnounceTier): Removed.
|
||||
(AnnounceTiers): Removed.
|
||||
* src/DefaultPieceStorage.h: New file.
|
||||
* src/Piece.cc (toString): New function.
|
||||
|
||||
To fix typo:
|
||||
|
||||
* src/main.cc (showVersion): Fixed typo.
|
||||
|
||||
To fix compile warning:
|
||||
|
||||
* src/DelegatingPeerListProcessor.cc
|
||||
(canHandle): Added "return false".
|
||||
|
||||
2006-10-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
|
||||
|
||||
To simplify TrackerWatherCommand, TrackerUpdateCommand and
|
||||
|
|
3
TODO
3
TODO
|
@ -19,4 +19,5 @@
|
|||
* Use SharedHandle where it is useful.
|
||||
* Add support for "announce-list".
|
||||
* Rewrite Util::countBit
|
||||
* Add the ability to display filename or URL to be downloaded in metalink mode.
|
||||
* Add the ability to display filename or URL to be downloaded in metalink mode.
|
||||
* Add Turkish translation.
|
||||
|
|
|
@ -59,7 +59,7 @@ void AnnounceList::reconfigure(const MetaEntry* announceListEntry) {
|
|||
urls.push_back(data->toString());
|
||||
}
|
||||
if(urls.size()) {
|
||||
AnnounceTier tier(urls);
|
||||
AnnounceTierHandle tier(new AnnounceTier(urls));
|
||||
tiers.push_back(tier);
|
||||
}
|
||||
}
|
||||
|
@ -70,14 +70,14 @@ void AnnounceList::reconfigure(const MetaEntry* announceListEntry) {
|
|||
void AnnounceList::reconfigure(const string& url) {
|
||||
Strings urls;
|
||||
urls.push_back(url);
|
||||
tiers.push_back(AnnounceTier(urls));
|
||||
tiers.push_back(AnnounceTierHandle(new AnnounceTier(urls)));
|
||||
resetIterator();
|
||||
}
|
||||
|
||||
void AnnounceList::resetIterator() {
|
||||
currentTier = tiers.begin();
|
||||
if(currentTier != tiers.end() && currentTier->urls.size()) {
|
||||
currentTracker = currentTier->urls.begin();
|
||||
if(currentTier != tiers.end() && (*currentTier)->urls.size()) {
|
||||
currentTracker = (*currentTier)->urls.begin();
|
||||
currentTrackerInitialized = true;
|
||||
} else {
|
||||
currentTrackerInitialized = false;
|
||||
|
@ -94,31 +94,31 @@ string AnnounceList::getAnnounce() const {
|
|||
|
||||
void AnnounceList::announceSuccess() {
|
||||
if(currentTrackerInitialized) {
|
||||
currentTier->nextEvent();
|
||||
(*currentTier)->nextEvent();
|
||||
string url = *currentTracker;
|
||||
currentTier->urls.erase(currentTracker);
|
||||
currentTier->urls.push_front(url);
|
||||
(*currentTier)->urls.erase(currentTracker);
|
||||
(*currentTier)->urls.push_front(url);
|
||||
currentTier = tiers.begin();
|
||||
currentTracker = currentTier->urls.begin();
|
||||
currentTracker = (*currentTier)->urls.begin();
|
||||
}
|
||||
}
|
||||
|
||||
void AnnounceList::announceFailure() {
|
||||
if(currentTrackerInitialized) {
|
||||
currentTracker++;
|
||||
if(currentTracker == currentTier->urls.end()) {
|
||||
if(currentTracker == (*currentTier)->urls.end()) {
|
||||
currentTier++;
|
||||
if(currentTier == tiers.end()) {
|
||||
currentTier = tiers.begin();
|
||||
}
|
||||
currentTracker = currentTier->urls.begin();
|
||||
currentTracker = (*currentTier)->urls.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnnounceTier::AnnounceEvent AnnounceList::getEvent() const {
|
||||
if(currentTrackerInitialized) {
|
||||
return currentTier->event;
|
||||
return (*currentTier)->event;
|
||||
} else {
|
||||
return AnnounceTier::STARTED;
|
||||
}
|
||||
|
@ -126,13 +126,13 @@ AnnounceTier::AnnounceEvent AnnounceList::getEvent() const {
|
|||
|
||||
void AnnounceList::setEvent(AnnounceTier::AnnounceEvent event) {
|
||||
if(currentTrackerInitialized) {
|
||||
currentTier->event = event;
|
||||
(*currentTier)->event = event;
|
||||
}
|
||||
}
|
||||
|
||||
string AnnounceList::getEventString() const {
|
||||
if(currentTrackerInitialized) {
|
||||
switch(currentTier->event) {
|
||||
switch((*currentTier)->event) {
|
||||
case AnnounceTier::STARTED:
|
||||
case AnnounceTier::STARTED_AFTER_COMPLETION:
|
||||
return "started";
|
||||
|
@ -150,8 +150,8 @@ string AnnounceList::getEventString() const {
|
|||
|
||||
class FindStoppedAllowedTier {
|
||||
public:
|
||||
bool operator()(const AnnounceTier& tier) const {
|
||||
switch(tier.event) {
|
||||
bool operator()(const AnnounceTierHandle& tier) const {
|
||||
switch(tier->event) {
|
||||
case AnnounceTier::DOWNLOADING:
|
||||
case AnnounceTier::STOPPED:
|
||||
case AnnounceTier::COMPLETED:
|
||||
|
@ -165,8 +165,8 @@ public:
|
|||
|
||||
class FindCompletedAllowedTier {
|
||||
public:
|
||||
bool operator()(const AnnounceTier& tier) const {
|
||||
switch(tier.event) {
|
||||
bool operator()(const AnnounceTierHandle& tier) const {
|
||||
switch(tier->event) {
|
||||
case AnnounceTier::DOWNLOADING:
|
||||
case AnnounceTier::COMPLETED:
|
||||
return true;
|
||||
|
@ -187,7 +187,7 @@ int AnnounceList::countCompletedAllowedTier() const {
|
|||
void AnnounceList::setCurrentTier(const AnnounceTiers::iterator& itr) {
|
||||
if(itr != tiers.end()) {
|
||||
currentTier = itr;
|
||||
currentTracker = currentTier->urls.begin();
|
||||
currentTracker = (*currentTier)->urls.begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,6 +220,7 @@ void AnnounceList::moveToCompletedAllowedTier() {
|
|||
void AnnounceList::shuffle() {
|
||||
for(AnnounceTiers::iterator itr = tiers.begin();
|
||||
itr != tiers.end(); itr++) {
|
||||
random_shuffle(itr->urls.begin(), itr->urls.end());
|
||||
Strings& urls = (*itr)->urls;
|
||||
random_shuffle(urls.begin(), urls.end());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,45 +37,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "MetaEntry.h"
|
||||
|
||||
class AnnounceTier {
|
||||
public:
|
||||
enum AnnounceEvent {
|
||||
STARTED,
|
||||
STARTED_AFTER_COMPLETION,
|
||||
DOWNLOADING,
|
||||
STOPPED,
|
||||
COMPLETED,
|
||||
SEEDING,
|
||||
HALTED
|
||||
};
|
||||
|
||||
AnnounceEvent event;
|
||||
Strings urls;
|
||||
|
||||
AnnounceTier(const Strings& urls):event(STARTED), urls(urls) {}
|
||||
|
||||
void nextEvent() {
|
||||
switch(event) {
|
||||
case STARTED:
|
||||
event = DOWNLOADING;
|
||||
break;
|
||||
case STARTED_AFTER_COMPLETION:
|
||||
event = SEEDING;
|
||||
break;
|
||||
case STOPPED:
|
||||
event = HALTED;
|
||||
break;
|
||||
case COMPLETED:
|
||||
event = SEEDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef deque<AnnounceTier> AnnounceTiers;
|
||||
#include "AnnounceTier.h"
|
||||
|
||||
class AnnounceList {
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_ANNOUNCE_TIER_H_
|
||||
#define _D_ANNOUNCE_TIER_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class AnnounceTier {
|
||||
public:
|
||||
enum AnnounceEvent {
|
||||
STARTED,
|
||||
STARTED_AFTER_COMPLETION,
|
||||
DOWNLOADING,
|
||||
STOPPED,
|
||||
COMPLETED,
|
||||
SEEDING,
|
||||
HALTED
|
||||
};
|
||||
|
||||
AnnounceEvent event;
|
||||
Strings urls;
|
||||
|
||||
AnnounceTier(const Strings& urls):event(STARTED), urls(urls) {}
|
||||
|
||||
void nextEvent() {
|
||||
switch(event) {
|
||||
case STARTED:
|
||||
event = DOWNLOADING;
|
||||
break;
|
||||
case STARTED_AFTER_COMPLETION:
|
||||
event = SEEDING;
|
||||
break;
|
||||
case STOPPED:
|
||||
event = HALTED;
|
||||
break;
|
||||
case COMPLETED:
|
||||
event = SEEDING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef SharedHandle<AnnounceTier> AnnounceTierHandle;
|
||||
typedef deque<AnnounceTierHandle> AnnounceTiers;
|
||||
|
||||
#endif // _D_ANNOUNCE_TIER_H_
|
|
@ -510,13 +510,17 @@ long long int BitfieldMan::getFilteredTotalLength() const {
|
|||
}
|
||||
}
|
||||
|
||||
long long int BitfieldMan::getCompletedLength() const {
|
||||
long long int BitfieldMan::getCompletedLength(bool useFilter) const {
|
||||
unsigned char* temp = new unsigned char[bitfieldLength];
|
||||
for(int i = 0; i < bitfieldLength; i++) {
|
||||
temp[i] = bitfield[i];
|
||||
if(filterEnabled) {
|
||||
temp[i] &= filterBitfield[i];
|
||||
if(useFilter) {
|
||||
for(int i = 0; i < bitfieldLength; i++) {
|
||||
temp[i] = bitfield[i];
|
||||
if(filterEnabled) {
|
||||
temp[i] &= filterBitfield[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(temp, bitfield, bitfieldLength);
|
||||
}
|
||||
int completedBlocks = countSetBit(temp, bitfieldLength);
|
||||
long long int completedLength = 0;
|
||||
|
@ -532,3 +536,11 @@ long long int BitfieldMan::getCompletedLength() const {
|
|||
delete [] temp;
|
||||
return completedLength;
|
||||
}
|
||||
|
||||
long long int BitfieldMan::getCompletedLength() const {
|
||||
return getCompletedLength(false);
|
||||
}
|
||||
|
||||
long long int BitfieldMan::getFilteredCompletedLength() const {
|
||||
return getCompletedLength(true);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ private:
|
|||
|
||||
int getStartIndex(int index) const;
|
||||
int getEndIndex(int index) const;
|
||||
|
||||
long long int getCompletedLength(bool useFilter) const;
|
||||
public:
|
||||
BitfieldMan(int blockLength, long long int totalLength);
|
||||
BitfieldMan(const BitfieldMan& bitfieldMan);
|
||||
|
@ -191,11 +193,15 @@ public:
|
|||
void enableFilter();
|
||||
void disableFilter();
|
||||
bool isFilterEnabled() const;
|
||||
long long int getFilteredTotalLength() const;
|
||||
/**
|
||||
* affected by filter
|
||||
*/
|
||||
long long int getFilteredTotalLength() const;
|
||||
long long int getCompletedLength() const;
|
||||
/**
|
||||
* affected by filter
|
||||
*/
|
||||
long long int getFilteredCompletedLength() const;
|
||||
};
|
||||
|
||||
#endif // _D_BITFIELD_MAN_H_
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_ANNOUNCE_H_
|
||||
#define _D_BT_ANNOUNCE_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class BtAnnounce {
|
||||
public:
|
||||
virtual ~BtAnnounce() {}
|
||||
|
||||
/**
|
||||
* Returns true if announce is required.
|
||||
* Otherwise returns false.
|
||||
*
|
||||
* There are 4 announce timings:
|
||||
* 1) started: when a download just started.
|
||||
* 2) stopped: when the client quits.
|
||||
* 3) completed: when a download just completed.
|
||||
* 4) When a certain amount of time, aka announce interval, specified by
|
||||
* a tracker, is elapsed.
|
||||
*/
|
||||
virtual bool isAnnounceReady() = 0;
|
||||
|
||||
/**
|
||||
* Returns announe URL with all necessary parameters included.
|
||||
*/
|
||||
virtual string getAnnounceUrl() = 0;
|
||||
|
||||
/**
|
||||
* Tells that the announce process has just started.
|
||||
*/
|
||||
virtual void announceStart() = 0;
|
||||
|
||||
/**
|
||||
* Tells that the announce succeeded.
|
||||
*/
|
||||
virtual void announceSuccess() = 0;
|
||||
|
||||
/**
|
||||
* Tells that the announce failed.
|
||||
*/
|
||||
virtual void announceFailure() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if all announce attempt failed.
|
||||
*/
|
||||
virtual bool isAllAnnounceFailed() = 0;
|
||||
|
||||
/**
|
||||
* Resets announce status.
|
||||
*/
|
||||
virtual void resetAnnounce() = 0;
|
||||
|
||||
/**
|
||||
* Processes the repsponse from the tracker.
|
||||
*/
|
||||
virtual void processAnnounceResponse(const char* trackerResponse,
|
||||
size_t trackerResponseLength) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if no more announce is needed.
|
||||
*/
|
||||
virtual bool noMoreAnnounce() = 0;
|
||||
|
||||
/**
|
||||
* Shuffles the URLs in each announce tier.
|
||||
*/
|
||||
virtual void shuffleAnnounce() = 0;
|
||||
|
||||
/**
|
||||
* Returns the peer id of the client.
|
||||
*/
|
||||
virtual string getPeerId() = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtAnnounce> BtAnnounceHandle;
|
||||
|
||||
#endif // _D_BT_ANNOUNCE_H_
|
|
@ -0,0 +1,84 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_CONTEXT_H_
|
||||
#define _D_BT_CONTEXT_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "FileEntry.h"
|
||||
#include "AnnounceTier.h"
|
||||
|
||||
#define INFO_HASH_LENGTH 20
|
||||
#define MAX_PEER_ERROR 5
|
||||
#define MAX_PEERS 55
|
||||
|
||||
typedef deque<AnnounceTierHandle> AnnounceTiers;
|
||||
|
||||
class BtContext {
|
||||
public:
|
||||
virtual ~BtContext() {}
|
||||
|
||||
enum FILE_MODE {
|
||||
SINGLE,
|
||||
MULTI
|
||||
};
|
||||
|
||||
virtual const unsigned char* getInfoHash() const = 0;
|
||||
|
||||
virtual int getInfoHashLength() const = 0;
|
||||
|
||||
virtual string getInfoHashAsString() const = 0;
|
||||
|
||||
virtual string getPieceHash(int index) const = 0;
|
||||
|
||||
virtual long long int getTotalLength() const = 0;
|
||||
|
||||
virtual FILE_MODE getFileMode() const = 0;
|
||||
|
||||
virtual FileEntries getFileEntries() const = 0;
|
||||
|
||||
virtual AnnounceTiers getAnnounceTiers() const = 0;
|
||||
|
||||
virtual void load(const string& torrentFile) = 0;
|
||||
|
||||
virtual string getName() const = 0;
|
||||
|
||||
virtual int getPieceLength() const = 0;
|
||||
|
||||
virtual int getNumPieces() const = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtContext> BtContextHandle;
|
||||
|
||||
#endif // _D_BT_CONTEXT_H_
|
|
@ -0,0 +1,48 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "BtRegistry.h"
|
||||
|
||||
BtContextAwareCommand::BtContextAwareCommand(int cuid,
|
||||
const BtContextHandle& btContext):
|
||||
Command(cuid),
|
||||
btContext(btContext),
|
||||
btRuntime(BT_RUNTIME(btContext)),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
peerStorage(PEER_STORAGE(btContext)),
|
||||
btAnnounce(BT_ANNOUNCE(btContext)),
|
||||
btProgressInfoFile(BT_PROGRESS_INFO_FILE(btContext)) {}
|
||||
|
||||
BtContextAwareCommand::~BtContextAwareCommand() {}
|
|
@ -0,0 +1,60 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_CONTEXT_AWARE_COMMAND_H_
|
||||
#define _D_BT_CONTEXT_AWARE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContext.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
|
||||
class BtContextAwareCommand : public Command {
|
||||
protected:
|
||||
BtContextHandle btContext;
|
||||
BtRuntimeHandle btRuntime;
|
||||
PieceStorageHandle pieceStorage;
|
||||
PeerStorageHandle peerStorage;
|
||||
BtAnnounceHandle btAnnounce;
|
||||
BtProgressInfoFileHandle btProgressInfoFile;
|
||||
public:
|
||||
BtContextAwareCommand(int cuid, const BtContextHandle& btContext);
|
||||
|
||||
virtual ~BtContextAwareCommand();
|
||||
};
|
||||
|
||||
#endif // _D_BT_CONTEXT_AWARE_COMMAND_H_
|
|
@ -0,0 +1,59 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_PROGRESS_INFO_FILE_H_
|
||||
#define _D_BT_PROGRESS_INFO_FILE_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class BtProgressInfoFile {
|
||||
public:
|
||||
virtual ~BtProgressInfoFile() {}
|
||||
|
||||
virtual string getFilename() = 0;
|
||||
|
||||
virtual void setFilename(const string& filename) = 0;
|
||||
|
||||
virtual bool exists() = 0;
|
||||
|
||||
virtual void save() = 0;
|
||||
|
||||
virtual void load() = 0;
|
||||
|
||||
virtual void removeFile() = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtProgressInfoFile> BtProgressInfoFileHandle;
|
||||
|
||||
#endif // _D_BT_PROGRESS_INFO_FILE_H_
|
|
@ -0,0 +1,130 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "BtRegistry.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
PeerStorageMap BtRegistry::peerStorageMap;
|
||||
PieceStorageMap BtRegistry::pieceStorageMap;
|
||||
BtAnnounceMap BtRegistry::btAnnounceMap;
|
||||
BtRuntimeMap BtRegistry::btRuntimeMap;
|
||||
BtProgressInfoFileMap BtRegistry::btProgressInfoFileMap;
|
||||
|
||||
PeerStorageHandle BtRegistry::getPeerStorage(const string& key) {
|
||||
PeerStorageMap::iterator itr = peerStorageMap.find(key);
|
||||
if(itr == peerStorageMap.end()) {
|
||||
return PeerStorageHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool BtRegistry::registerPeerStorage(const string& key,
|
||||
const PeerStorageHandle& peerStorage) {
|
||||
PeerStorageMap::value_type p(key, peerStorage);
|
||||
pair<PeerStorageMap::iterator, bool> retval = peerStorageMap.insert(p);
|
||||
return retval.second;
|
||||
}
|
||||
|
||||
PieceStorageHandle
|
||||
BtRegistry::getPieceStorage(const string& key) {
|
||||
PieceStorageMap::iterator itr = pieceStorageMap.find(key);
|
||||
if(itr == pieceStorageMap.end()) {
|
||||
return PieceStorageHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BtRegistry::registerPieceStorage(const string& key,
|
||||
const PieceStorageHandle& pieceStorage) {
|
||||
PieceStorageMap::value_type p(key, pieceStorage);
|
||||
pair<PieceStorageMap::iterator, bool> retval = pieceStorageMap.insert(p);
|
||||
return retval.second;
|
||||
}
|
||||
|
||||
BtRuntimeHandle BtRegistry::getBtRuntime(const string& key) {
|
||||
BtRuntimeMap::iterator itr = btRuntimeMap.find(key);
|
||||
if(itr == btRuntimeMap.end()) {
|
||||
return BtRuntimeHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BtRegistry::registerBtRuntime(const string& key,
|
||||
const BtRuntimeHandle& btRuntime) {
|
||||
BtRuntimeMap::value_type p(key, btRuntime);
|
||||
pair<BtRuntimeMap::iterator, bool> retval =
|
||||
btRuntimeMap.insert(p);
|
||||
return retval.second;
|
||||
}
|
||||
|
||||
BtAnnounceHandle BtRegistry::getBtAnnounce(const string& key) {
|
||||
BtAnnounceMap::iterator itr = btAnnounceMap.find(key);
|
||||
if(itr == btAnnounceMap.end()) {
|
||||
return BtAnnounceHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BtRegistry::registerBtAnnounce(const string& key,
|
||||
const BtAnnounceHandle& btAnnounce) {
|
||||
BtAnnounceMap::value_type p(key, btAnnounce);
|
||||
pair<BtAnnounceMap::iterator, bool> retval =
|
||||
btAnnounceMap.insert(p);
|
||||
return retval.second;
|
||||
}
|
||||
|
||||
BtProgressInfoFileHandle BtRegistry::getBtProgressInfoFile(const string& key) {
|
||||
BtProgressInfoFileMap::iterator itr = btProgressInfoFileMap.find(key);
|
||||
if(itr == btProgressInfoFileMap.end()) {
|
||||
return BtProgressInfoFileHandle(0);
|
||||
} else {
|
||||
return itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BtRegistry::registerBtProgressInfoFile(const string& key,
|
||||
const BtProgressInfoFileHandle& btProgressInfoFile) {
|
||||
BtProgressInfoFileMap::value_type p(key, btProgressInfoFile);
|
||||
pair<BtProgressInfoFileMap::iterator, bool> retval =
|
||||
btProgressInfoFileMap.insert(p);
|
||||
return retval.second;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_REGISTRY_H_
|
||||
#define _D_BT_REGISTRY_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
#include <map>
|
||||
|
||||
typedef map<string, PeerStorageHandle> PeerStorageMap;
|
||||
typedef map<string, PieceStorageHandle> PieceStorageMap;
|
||||
typedef map<string, BtAnnounceHandle> BtAnnounceMap;
|
||||
typedef map<string, BtRuntimeHandle> BtRuntimeMap;
|
||||
typedef map<string, BtProgressInfoFileHandle> BtProgressInfoFileMap;
|
||||
|
||||
class BtRegistry {
|
||||
private:
|
||||
BtRegistry() {}
|
||||
|
||||
static PeerStorageMap peerStorageMap;
|
||||
static PieceStorageMap pieceStorageMap;
|
||||
static BtAnnounceMap btAnnounceMap;
|
||||
static BtRuntimeMap btRuntimeMap;
|
||||
static BtProgressInfoFileMap btProgressInfoFileMap;
|
||||
public:
|
||||
static PeerStorageHandle getPeerStorage(const string& key);
|
||||
static bool registerPeerStorage(const string& key,
|
||||
const PeerStorageHandle& peer);
|
||||
|
||||
static PieceStorageHandle getPieceStorage(const string& key);
|
||||
static bool registerPieceStorage(const string& key,
|
||||
const PieceStorageHandle& pieceStorage);
|
||||
|
||||
static BtRuntimeHandle getBtRuntime(const string& key);
|
||||
static bool registerBtRuntime(const string& key,
|
||||
const BtRuntimeHandle& btRuntime);
|
||||
|
||||
static BtAnnounceHandle getBtAnnounce(const string& key);
|
||||
static bool registerBtAnnounce(const string& key,
|
||||
const BtAnnounceHandle& btAnnounce);
|
||||
|
||||
static BtProgressInfoFileHandle getBtProgressInfoFile(const string& key);
|
||||
static bool registerBtProgressInfoFile(const string& key,
|
||||
const BtProgressInfoFileHandle& btProgressInfoFile);
|
||||
};
|
||||
|
||||
#define PEER_STORAGE(btContext) \
|
||||
BtRegistry::getPeerStorage(btContext->getInfoHashAsString())
|
||||
|
||||
#define PIECE_STORAGE(btContext) \
|
||||
BtRegistry::getPieceStorage(btContext->getInfoHashAsString())
|
||||
|
||||
#define BT_ANNOUNCE(btContext) \
|
||||
BtRegistry::getBtAnnounce(btContext->getInfoHashAsString())
|
||||
|
||||
#define BT_RUNTIME(btContext) \
|
||||
BtRegistry::getBtRuntime(btContext->getInfoHashAsString())
|
||||
|
||||
#define BT_PROGRESS_INFO_FILE(btContext) \
|
||||
BtRegistry::getBtProgressInfoFile(btContext->getInfoHashAsString())
|
||||
|
||||
#endif // _D_BT_REGISTRY_H_
|
|
@ -0,0 +1,94 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_BT_RUNTIME_H_
|
||||
#define _D_BT_RUNTIME_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "SharedHandle.h"
|
||||
|
||||
#define MIN_PEERS 15
|
||||
|
||||
class BtRuntime {
|
||||
private:
|
||||
long long int uploadLengthAtStartup;
|
||||
int port;
|
||||
bool halt;
|
||||
int connections;
|
||||
int cuidCounter;
|
||||
public:
|
||||
BtRuntime():
|
||||
uploadLengthAtStartup(0),
|
||||
port(0),
|
||||
halt(false),
|
||||
connections(0),
|
||||
cuidCounter(0) {}
|
||||
~BtRuntime() {}
|
||||
|
||||
long long int getUploadLengthAtStartup() const {
|
||||
return uploadLengthAtStartup;
|
||||
}
|
||||
|
||||
void setUploadLengthAtStartup(long long int length) {
|
||||
this->uploadLengthAtStartup = length;
|
||||
}
|
||||
|
||||
void setListenPort(int port) {
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
int getListenPort() const { return port; }
|
||||
|
||||
bool isHalt() const { return halt; }
|
||||
|
||||
void setHalt(bool halt) {
|
||||
this->halt = halt;
|
||||
}
|
||||
|
||||
int getConnections() const { return connections; }
|
||||
|
||||
void increaseConnections() { connections++; }
|
||||
|
||||
void decreaseConnections() { connections--; }
|
||||
|
||||
bool lessThanMinPeer() const { return connections < MIN_PEERS; }
|
||||
|
||||
bool lessThanEqMinPeer() const { return connections <= MIN_PEERS; }
|
||||
|
||||
int getNewCuid() { return ++cuidCounter; }
|
||||
};
|
||||
|
||||
typedef SharedHandle<BtRuntime> BtRuntimeHandle;
|
||||
|
||||
#endif // _D_BT_RUNTIME_H_
|
|
@ -36,7 +36,6 @@
|
|||
#define _D_CANCEL_MESSAGE_H_
|
||||
|
||||
#include "SimplePeerMessage.h"
|
||||
#include "TorrentMan.h"
|
||||
|
||||
class CancelMessage : public SimplePeerMessage {
|
||||
private:
|
||||
|
|
|
@ -68,7 +68,7 @@ void CookieBox::setField(Cookie& cookie, const string& name, const string& value
|
|||
void CookieBox::parse(Cookie& cookie, const string& cookieStr) const {
|
||||
cookie.clear();
|
||||
Strings terms;
|
||||
Util::slice(terms, cookieStr, ';');
|
||||
Util::slice(terms, cookieStr, ';', true);
|
||||
for(Strings::iterator itr = terms.begin(); itr != terms.end(); itr++) {
|
||||
pair<string, string> nv;
|
||||
Util::split(nv, *itr, '=');
|
||||
|
|
|
@ -46,19 +46,17 @@ void CopyDiskAdaptor::onDownloadComplete() {
|
|||
}
|
||||
|
||||
void CopyDiskAdaptor::fixFilename() {
|
||||
if(topDir != NULL) {
|
||||
topDir->createDir(storeDir, true);
|
||||
}
|
||||
long long int offset = 0;
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
if(!itr->extracted && itr->requested) {
|
||||
string dest = storeDir+"/"+itr->path;
|
||||
if(!(*itr)->isExtracted() && (*itr)->isRequested()) {
|
||||
(*itr)->setupDir(storeDir);
|
||||
string dest = storeDir+"/"+(*itr)->getPath();
|
||||
logger->info("writing file %s", dest.c_str());
|
||||
Util::rangedFileCopy(dest, getFilePath(), offset, itr->length);
|
||||
itr->extracted = true;
|
||||
Util::rangedFileCopy(dest, getFilePath(), offset, (*itr)->getLength());
|
||||
(*itr)->setExtracted(true);
|
||||
}
|
||||
offset += itr->length;
|
||||
offset += (*itr)->getLength();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultBtAnnounce.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "LogFactory.h"
|
||||
#include "MetaFileUtil.h"
|
||||
#include "Dictionary.h"
|
||||
#include "List.h"
|
||||
#include "Data.h"
|
||||
#include "DelegatingPeerListProcessor.h"
|
||||
#include "Util.h"
|
||||
#include "prefs.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "message.h"
|
||||
|
||||
DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext,
|
||||
const Option* option):
|
||||
btContext(btContext),
|
||||
trackers(0),
|
||||
interval(DEFAULT_ANNOUNCE_INTERVAL),
|
||||
minInterval(DEFAULT_ANNOUNCE_INTERVAL),
|
||||
complete(0),
|
||||
incomplete(0),
|
||||
announceList(btContext->getAnnounceTiers()),
|
||||
trackerNumTry(0),
|
||||
option(option),
|
||||
btRuntime(BT_RUNTIME(btContext)),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
peerStorage(PEER_STORAGE(btContext))
|
||||
{
|
||||
prevAnnounceTime.setTimeInSec(0);
|
||||
key = generateKey();
|
||||
peerId = generatePeerId();
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
DefaultBtAnnounce::~DefaultBtAnnounce() {
|
||||
}
|
||||
|
||||
string DefaultBtAnnounce::generateKey() const {
|
||||
return Util::randomAlpha(8);
|
||||
}
|
||||
|
||||
string DefaultBtAnnounce::generatePeerId() const {
|
||||
string peerId = "-aria2-";
|
||||
peerId += Util::randomAlpha(20-peerId.size());
|
||||
return peerId;
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::isDefaultAnnounceReady() {
|
||||
return (trackers == 0 && prevAnnounceTime.elapsed(minInterval));
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::isStoppedAnnounceReady() {
|
||||
return (trackers == 0 &&
|
||||
btRuntime->isHalt() &&
|
||||
announceList.countStoppedAllowedTier());
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::isCompletedAnnounceReady() {
|
||||
return (trackers == 0 &&
|
||||
pieceStorage->downloadFinished() &&
|
||||
announceList.countCompletedAllowedTier());
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::isAnnounceReady() {
|
||||
return
|
||||
isStoppedAnnounceReady() ||
|
||||
isCompletedAnnounceReady() ||
|
||||
isDefaultAnnounceReady();
|
||||
}
|
||||
|
||||
string DefaultBtAnnounce::getAnnounceUrl() {
|
||||
if(isStoppedAnnounceReady()) {
|
||||
announceList.moveToStoppedAllowedTier();
|
||||
announceList.setEvent(AnnounceTier::STOPPED);
|
||||
} else if(isCompletedAnnounceReady()) {
|
||||
announceList.moveToCompletedAllowedTier();
|
||||
announceList.setEvent(AnnounceTier::COMPLETED);
|
||||
} else if(isDefaultAnnounceReady()) {
|
||||
// If download completed before "started" event is sent to a tracker,
|
||||
// we change the event to something else to prevent us from
|
||||
// sending "completed" event.
|
||||
if(pieceStorage->downloadFinished() &&
|
||||
announceList.getEvent() == AnnounceTier::STARTED) {
|
||||
announceList.setEvent(AnnounceTier::STARTED_AFTER_COMPLETION);
|
||||
}
|
||||
}
|
||||
int numWant = 50;
|
||||
if(!btRuntime->lessThanEqMinPeer() ||
|
||||
btRuntime->isHalt()) {
|
||||
numWant = 0;
|
||||
}
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
long long int left = pieceStorage->getTotalLength()-pieceStorage->getCompletedLength();
|
||||
if(left < 0) {
|
||||
left = 0;
|
||||
}
|
||||
string url = announceList.getAnnounce()+"?"+
|
||||
"info_hash="+Util::torrentUrlencode(btContext->getInfoHash(),
|
||||
btContext->getInfoHashLength())+"&"+
|
||||
"peer_id="+peerId+"&"+
|
||||
"port="+Util::itos(btRuntime->getListenPort())+"&"+
|
||||
"uploaded="+Util::llitos(stat.getSessionUploadLength())+"&"+
|
||||
"downloaded="+Util::llitos(stat.getSessionDownloadLength())+"&"+
|
||||
"left="+Util::llitos(left)+"&"+
|
||||
"compact=1"+"&"+
|
||||
"key="+key+"&"+
|
||||
"numwant="+Util::itos(numWant)+"&"+
|
||||
"no_peer_id=1";
|
||||
string event = announceList.getEventString();
|
||||
if(!event.empty()) {
|
||||
url += string("&")+"event="+event;
|
||||
}
|
||||
if(!trackerId.empty()) {
|
||||
url += string("&")+"trackerid="+Util::torrentUrlencode((const unsigned char*)trackerId.c_str(),
|
||||
trackerId.size());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
void DefaultBtAnnounce::announceStart() {
|
||||
trackers++;
|
||||
}
|
||||
|
||||
void DefaultBtAnnounce::announceSuccess() {
|
||||
trackers = 0;
|
||||
announceList.announceSuccess();
|
||||
}
|
||||
|
||||
void DefaultBtAnnounce::announceFailure() {
|
||||
trackers = 0;
|
||||
trackerNumTry++;
|
||||
announceList.announceFailure();
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::isAllAnnounceFailed() {
|
||||
return
|
||||
trackerNumTry >= option->getAsInt(PREF_TRACKER_MAX_TRIES);
|
||||
}
|
||||
|
||||
void DefaultBtAnnounce::resetAnnounce() {
|
||||
prevAnnounceTime.reset();
|
||||
trackerNumTry = 0;
|
||||
}
|
||||
|
||||
void
|
||||
DefaultBtAnnounce::processAnnounceResponse(const char* trackerResponse,
|
||||
size_t trackerResponseLength)
|
||||
{
|
||||
SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse,
|
||||
trackerResponseLength));
|
||||
Dictionary* response = (Dictionary*)entry.get();
|
||||
Data* failureReasonData = (Data*)response->get("failure reason");
|
||||
if(failureReasonData) {
|
||||
throw new DlAbortEx("Tracker returned failure reason: %s",
|
||||
failureReasonData->toString().c_str());
|
||||
}
|
||||
Data* warningMessageData = (Data*)response->get("warning message");
|
||||
if(warningMessageData) {
|
||||
logger->warn(MSG_TRACKER_WARNING_MESSAGE,
|
||||
warningMessageData->toString().c_str());
|
||||
}
|
||||
Data* trackerIdData = (Data*)response->get("tracker id");
|
||||
if(trackerIdData) {
|
||||
trackerId = trackerIdData->toString();
|
||||
logger->debug("Tracker ID:%s", trackerId.c_str());
|
||||
}
|
||||
Data* intervalData = (Data*)response->get("interval");
|
||||
if(intervalData) {
|
||||
interval = intervalData->toInt();
|
||||
logger->debug("Interval:%d", interval);
|
||||
}
|
||||
Data* minIntervalData = (Data*)response->get("min interval");
|
||||
if(minIntervalData) {
|
||||
minInterval = minIntervalData->toInt();
|
||||
logger->debug("Min interval:%d", minInterval);
|
||||
}
|
||||
if(minInterval > interval) {
|
||||
minInterval = interval;
|
||||
}
|
||||
Data* completeData = (Data*)response->get("complete");
|
||||
if(completeData) {
|
||||
complete = completeData->toInt();
|
||||
logger->debug("Complete:%d", complete);
|
||||
}
|
||||
Data* incompleteData = (Data*)response->get("incomplete");
|
||||
if(incompleteData) {
|
||||
incomplete = incompleteData->toInt();
|
||||
logger->debug("Incomplete:%d", incomplete);
|
||||
}
|
||||
const MetaEntry* peersEntry = response->get("peers");
|
||||
if(peersEntry &&
|
||||
!btRuntime->isHalt() &&
|
||||
btRuntime->lessThanMinPeer()) {
|
||||
DelegatingPeerListProcessor proc(btContext->getPieceLength(),
|
||||
btContext->getTotalLength());
|
||||
Peers peers = proc.extractPeer(peersEntry);
|
||||
peerStorage->addPeer(peers);
|
||||
}
|
||||
if(!peersEntry) {
|
||||
logger->info("No peer list received.");
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultBtAnnounce::noMoreAnnounce() {
|
||||
return (trackers == 0 &&
|
||||
btRuntime->isHalt() &&
|
||||
!announceList.countStoppedAllowedTier());
|
||||
}
|
||||
|
||||
void DefaultBtAnnounce::shuffleAnnounce() {
|
||||
announceList.shuffle();
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_BT_ANNOUNCE_H_
|
||||
#define _D_DEFAULT_BT_ANNOUNCE_H_
|
||||
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtContext.h"
|
||||
#include "TimeA2.h"
|
||||
#include "AnnounceList.h"
|
||||
#include "Option.h"
|
||||
#include "Logger.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "PeerStorage.h"
|
||||
|
||||
#define DEFAULT_ANNOUNCE_INTERVAL 1800
|
||||
|
||||
class DefaultBtAnnounce : public BtAnnounce {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
int trackers;
|
||||
Time prevAnnounceTime;
|
||||
int interval;
|
||||
int minInterval;
|
||||
int complete;
|
||||
int incomplete;
|
||||
AnnounceList announceList;
|
||||
string trackerId;
|
||||
string key;
|
||||
int trackerNumTry;
|
||||
string peerId;
|
||||
const Option* option;
|
||||
Logger* logger;
|
||||
BtRuntimeHandle btRuntime;
|
||||
PieceStorageHandle pieceStorage;
|
||||
PeerStorageHandle peerStorage;
|
||||
public:
|
||||
DefaultBtAnnounce(BtContextHandle btContext, const Option* option);
|
||||
virtual ~DefaultBtAnnounce();
|
||||
|
||||
void setBtRuntime(const BtRuntimeHandle& btRuntime) {
|
||||
this->btRuntime = btRuntime;
|
||||
}
|
||||
BtRuntimeHandle getBtRuntime() const { return btRuntime; }
|
||||
|
||||
void setPieceStorage(const PieceStorageHandle& pieceStorage) {
|
||||
this->pieceStorage = pieceStorage;
|
||||
}
|
||||
PieceStorageHandle getPieceStorage() const { return pieceStorage; }
|
||||
|
||||
void setPeerStorage(const PeerStorageHandle& peerStorage) {
|
||||
this->peerStorage = peerStorage;
|
||||
}
|
||||
PeerStorageHandle getPeerStorage() const { return peerStorage; }
|
||||
|
||||
bool isDefaultAnnounceReady();
|
||||
|
||||
bool isStoppedAnnounceReady();
|
||||
|
||||
bool isCompletedAnnounceReady();
|
||||
|
||||
virtual bool isAnnounceReady();
|
||||
|
||||
virtual string getAnnounceUrl();
|
||||
|
||||
virtual void announceStart();
|
||||
|
||||
virtual void announceSuccess();
|
||||
|
||||
virtual void announceFailure();
|
||||
|
||||
virtual bool isAllAnnounceFailed();
|
||||
|
||||
virtual void resetAnnounce();
|
||||
|
||||
virtual void processAnnounceResponse(const char* trackerResponse,
|
||||
size_t trackerResponseLength);
|
||||
|
||||
virtual bool noMoreAnnounce();
|
||||
|
||||
virtual void shuffleAnnounce();
|
||||
|
||||
string generateKey() const;
|
||||
|
||||
string generatePeerId() const;
|
||||
|
||||
virtual string getPeerId() { return peerId; }
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_BT_ANNOUNCE_H_
|
|
@ -0,0 +1,237 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultBtContext.h"
|
||||
#include "MetaFileUtil.h"
|
||||
#include "Dictionary.h"
|
||||
#include "List.h"
|
||||
#include "Data.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "ShaVisitor.h"
|
||||
#include "Util.h"
|
||||
|
||||
DefaultBtContext::DefaultBtContext() {}
|
||||
|
||||
DefaultBtContext::~DefaultBtContext() {}
|
||||
|
||||
const unsigned char* DefaultBtContext::getInfoHash() const {
|
||||
return infoHash;
|
||||
}
|
||||
|
||||
int DefaultBtContext::getInfoHashLength() const {
|
||||
return INFO_HASH_LENGTH;
|
||||
}
|
||||
|
||||
string DefaultBtContext::getInfoHashAsString() const {
|
||||
return infoHashString;
|
||||
}
|
||||
|
||||
void DefaultBtContext::clear() {
|
||||
memset(infoHash, 0, INFO_HASH_LENGTH);
|
||||
infoHashString = "";
|
||||
pieceHashes.clear();
|
||||
fileEntries.clear();
|
||||
totalLength = 0;
|
||||
pieceLength = 0;
|
||||
fileMode = BtContext::SINGLE;
|
||||
numPieces = 0;
|
||||
name = "";
|
||||
announceTiers.clear();
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractPieceHash(const unsigned char* hashData,
|
||||
int hashDataLength,
|
||||
int hashLength) {
|
||||
assert(hashDataLength > 0);
|
||||
assert(hashLength > 0);
|
||||
int numPieces = hashDataLength/hashLength;
|
||||
assert(numPieces > 0);
|
||||
|
||||
for(int i = 0; i < numPieces; i++) {
|
||||
pieceHashes.push_back(Util::toHex(&hashData[i*hashLength],
|
||||
hashLength));
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
|
||||
const string& defaultName) {
|
||||
// TODO use dynamic_cast
|
||||
Data* nameData = (Data*)infoDic->get("name");
|
||||
if(nameData) {
|
||||
name = nameData->toString();
|
||||
} else {
|
||||
char* basec = strdup(defaultName.c_str());
|
||||
name = string(basename(basec))+".file";
|
||||
free(basec);
|
||||
}
|
||||
// TODO use dynamic_cast
|
||||
List* files = (List*)infoDic->get("files");
|
||||
if(files) {
|
||||
long long int length = 0;
|
||||
long long int offset = 0;
|
||||
// multi-file mode
|
||||
fileMode = BtContext::MULTI;
|
||||
const MetaList& metaList = files->getList();
|
||||
for(MetaList::const_iterator itr = metaList.begin();
|
||||
itr != metaList.end(); itr++) {
|
||||
Dictionary* fileDic = (Dictionary*)(*itr);
|
||||
// TODO use dynamic_cast
|
||||
Data* lengthData = (Data*)fileDic->get("length");
|
||||
length += lengthData->toLLInt();
|
||||
// TODO use dynamic_cast
|
||||
List* pathList = (List*)fileDic->get("path");
|
||||
const MetaList& paths = pathList->getList();
|
||||
string path;
|
||||
for(int i = 0; i < (int)paths.size()-1; i++) {
|
||||
Data* subpath = (Data*)paths.at(i);
|
||||
path += subpath->toString()+"/";
|
||||
}
|
||||
// TODO use dynamic_cast
|
||||
Data* lastPath = (Data*)paths.back();
|
||||
path += lastPath->toString();
|
||||
|
||||
FileEntryHandle fileEntry(new FileEntry(path,
|
||||
lengthData->toLLInt(),
|
||||
offset));
|
||||
fileEntries.push_back(fileEntry);
|
||||
offset += fileEntry->getLength();
|
||||
}
|
||||
totalLength = length;
|
||||
} else {
|
||||
// single-file mode;
|
||||
fileMode = BtContext::SINGLE;
|
||||
Data* length = (Data*)infoDic->get("length");
|
||||
totalLength = length->toLLInt();
|
||||
FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0));
|
||||
fileEntries.push_back(fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractAnnounce(Data* announceData) {
|
||||
Strings urls;
|
||||
urls.push_back(announceData->toString());
|
||||
announceTiers.push_back(AnnounceTierHandle(new AnnounceTier(urls)));
|
||||
}
|
||||
|
||||
void DefaultBtContext::extractAnnounceList(List* announceListData) {
|
||||
for(MetaList::const_iterator itr = announceListData->getList().begin();
|
||||
itr != announceListData->getList().end(); itr++) {
|
||||
const List* elem = (List*)*itr;
|
||||
Strings urls;
|
||||
for(MetaList::const_iterator elemItr = elem->getList().begin();
|
||||
elemItr != elem->getList().end(); elemItr++) {
|
||||
const Data* data = (Data*)*elemItr;
|
||||
urls.push_back(data->toString());
|
||||
}
|
||||
if(urls.size()) {
|
||||
AnnounceTierHandle tier(new AnnounceTier(urls));
|
||||
announceTiers.push_back(tier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtContext::load(const string& torrentFile) {
|
||||
clear();
|
||||
MetaEntry* rootEntry = MetaFileUtil::parseMetaFile(torrentFile);
|
||||
if(!dynamic_cast<Dictionary*>(rootEntry)) {
|
||||
throw new DlAbortEx("torrent file does not contain a root dictionary .");
|
||||
}
|
||||
SharedHandle<Dictionary> rootDic =
|
||||
SharedHandle<Dictionary>((Dictionary*)rootEntry);
|
||||
Dictionary* infoDic = (Dictionary*)rootDic->get("info");
|
||||
// retrieve infoHash
|
||||
ShaVisitor v;
|
||||
infoDic->accept(&v);
|
||||
int len;
|
||||
v.getHash(infoHash, len);
|
||||
infoHashString = Util::toHex(infoHash, INFO_HASH_LENGTH);
|
||||
// calculate the number of pieces
|
||||
Data* pieceHashData = (Data*)infoDic->get("pieces");
|
||||
numPieces = pieceHashData->getLen()/PIECE_HASH_LENGTH;
|
||||
// retrieve piece length
|
||||
Data* pieceLengthData = (Data*)infoDic->get("piece length");
|
||||
pieceLength = pieceLengthData->toInt();
|
||||
// retrieve piece hashes
|
||||
extractPieceHash((unsigned char*)pieceHashData->getData(),
|
||||
pieceHashData->getLen(),
|
||||
PIECE_HASH_LENGTH);
|
||||
// retrieve file entries
|
||||
extractFileEntries(infoDic, torrentFile);
|
||||
// retrieve announce
|
||||
Data* announceData = (Data*)rootDic->get("announce");
|
||||
List* announceListData = (List*)rootDic->get("announce-list");
|
||||
if(announceListData) {
|
||||
extractAnnounceList(announceListData);
|
||||
} else if(announceData) {
|
||||
extractAnnounce(announceData);
|
||||
}
|
||||
if(!announceTiers.size()) {
|
||||
throw new DlAbortEx("No announce URL found.");
|
||||
}
|
||||
}
|
||||
|
||||
string DefaultBtContext::getPieceHash(int index) const {
|
||||
if(index < 0 || numPieces <= index) {
|
||||
return "";
|
||||
}
|
||||
return pieceHashes.at(index);
|
||||
}
|
||||
|
||||
long long int DefaultBtContext::getTotalLength() const {
|
||||
return totalLength;
|
||||
}
|
||||
|
||||
BtContext::FILE_MODE DefaultBtContext::getFileMode() const {
|
||||
return fileMode;
|
||||
}
|
||||
|
||||
FileEntries DefaultBtContext::getFileEntries() const {
|
||||
return fileEntries;
|
||||
}
|
||||
|
||||
AnnounceTiers DefaultBtContext::getAnnounceTiers() const {
|
||||
return announceTiers;
|
||||
}
|
||||
|
||||
string DefaultBtContext::getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
int DefaultBtContext::getPieceLength() const {
|
||||
return pieceLength;
|
||||
}
|
||||
|
||||
int DefaultBtContext::getNumPieces() const {
|
||||
return numPieces;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_BT_CONTEXT_H_
|
||||
#define _D_DEFAULT_BT_CONTEXT_H_
|
||||
|
||||
#include "BtContext.h"
|
||||
#include "Dictionary.h"
|
||||
#include "Data.h"
|
||||
#include "List.h"
|
||||
#define INFO_HASH_LENGTH 20
|
||||
#define PIECE_HASH_LENGTH 20
|
||||
|
||||
typedef Strings PieceHashes;
|
||||
|
||||
class DefaultBtContext : public BtContext {
|
||||
private:
|
||||
unsigned char infoHash[INFO_HASH_LENGTH];
|
||||
string infoHashString;
|
||||
PieceHashes pieceHashes;
|
||||
FileEntries fileEntries;
|
||||
FILE_MODE fileMode;
|
||||
long long int totalLength;
|
||||
int pieceLength;
|
||||
string name;
|
||||
int numPieces;
|
||||
AnnounceTiers announceTiers;
|
||||
|
||||
void clear();
|
||||
void extractPieceHash(const unsigned char* hashData,
|
||||
int hashDataLength,
|
||||
int hashLength);
|
||||
void extractFileEntries(Dictionary* infoDic,
|
||||
const string& defaultName);
|
||||
void extractAnnounce(Data* announceData);
|
||||
void extractAnnounceList(List* announceListData);
|
||||
public:
|
||||
DefaultBtContext();
|
||||
virtual ~DefaultBtContext();
|
||||
|
||||
virtual const unsigned char* getInfoHash() const;
|
||||
|
||||
virtual int getInfoHashLength() const;
|
||||
|
||||
virtual string getInfoHashAsString() const;
|
||||
|
||||
virtual string getPieceHash(int index) const;
|
||||
|
||||
virtual long long int getTotalLength() const;
|
||||
|
||||
virtual FILE_MODE getFileMode() const;
|
||||
|
||||
virtual FileEntries getFileEntries() const;
|
||||
|
||||
virtual AnnounceTiers getAnnounceTiers() const;
|
||||
|
||||
virtual void load(const string& torrentFile);
|
||||
|
||||
virtual string getName() const;
|
||||
|
||||
virtual int getPieceLength() const;
|
||||
|
||||
virtual int getNumPieces() const;
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_BT_CONTEXT_H_
|
|
@ -0,0 +1,172 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultBtProgressInfoFile.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "LogFactory.h"
|
||||
#include "prefs.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "message.h"
|
||||
#include "File.h"
|
||||
#include "Util.h"
|
||||
#include <errno.h>
|
||||
|
||||
DefaultBtProgressInfoFile::DefaultBtProgressInfoFile(const BtContextHandle& btContext,
|
||||
const Option* option):
|
||||
btContext(btContext),
|
||||
option(option),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
btRuntime(BT_RUNTIME(btContext)),
|
||||
peerStorage(PEER_STORAGE(btContext))
|
||||
{
|
||||
logger = LogFactory::getInstance();
|
||||
string storeDir = option->get(PREF_DIR);
|
||||
filename = storeDir+"/"+btContext->getName()+".aria2";
|
||||
}
|
||||
|
||||
DefaultBtProgressInfoFile::~DefaultBtProgressInfoFile() {}
|
||||
|
||||
void DefaultBtProgressInfoFile::save() {
|
||||
logger->info(MSG_SAVING_SEGMENT_FILE, filename.c_str());
|
||||
FILE* file = openFile(filename, "w");
|
||||
try {
|
||||
if(fwrite(btContext->getInfoHash(),
|
||||
btContext->getInfoHashLength(), 1, file) < 1) {
|
||||
throw string("writeError:info hash");
|
||||
}
|
||||
if(fwrite(pieceStorage->getBitfield(),
|
||||
pieceStorage->getBitfieldLength(), 1, file) < 1) {
|
||||
throw string("writeError:bitfield");
|
||||
}
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
long long int allTimeDownloadLength = pieceStorage->getCompletedLength();
|
||||
if(fwrite(&allTimeDownloadLength,
|
||||
sizeof(allTimeDownloadLength), 1, file) < 1) {
|
||||
throw string("writeError:download length");
|
||||
}
|
||||
long long int allTimeUploadLength =
|
||||
btRuntime->getUploadLengthAtStartup()+
|
||||
stat.getSessionUploadLength();
|
||||
if(fwrite(&allTimeUploadLength,
|
||||
sizeof(allTimeUploadLength), 1, file) < 1) {
|
||||
throw string("writeError:upload length");
|
||||
}
|
||||
fclose(file);
|
||||
logger->info(MSG_SAVED_SEGMENT_FILE);
|
||||
} catch(string ex) {
|
||||
fclose(file);
|
||||
throw new DlAbortEx(EX_SEGMENT_FILE_WRITE,
|
||||
filename.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFile::load() {
|
||||
logger->info(MSG_LOADING_SEGMENT_FILE, filename.c_str());
|
||||
FILE* file = openFile(filename, "r+");
|
||||
unsigned char* savedInfoHash = 0;
|
||||
unsigned char* savedBitfield = 0;
|
||||
try {
|
||||
savedInfoHash = new unsigned char[btContext->getInfoHashLength()];
|
||||
savedBitfield = new unsigned char[pieceStorage->getBitfieldLength()];
|
||||
if(fread(savedInfoHash, btContext->getInfoHashLength(), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
}
|
||||
if(Util::toHex(savedInfoHash, btContext->getInfoHashLength()) !=
|
||||
btContext->getInfoHashAsString()) {
|
||||
throw new DlAbortEx("Incorrect infoHash.");
|
||||
}
|
||||
if(fread(savedBitfield, pieceStorage->getBitfieldLength(), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
}
|
||||
pieceStorage->setBitfield(savedBitfield,
|
||||
pieceStorage->getBitfieldLength());
|
||||
// allTimeDownloadLength exists for only a compatibility reason.
|
||||
long long int allTimeDownloadLength;
|
||||
if(fread(&allTimeDownloadLength,
|
||||
sizeof(allTimeDownloadLength), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
}
|
||||
long long int allTimeUploadLength;
|
||||
if(fread(&allTimeUploadLength,
|
||||
sizeof(allTimeUploadLength), 1, file) < 1) {
|
||||
throw string("readError");
|
||||
}
|
||||
btRuntime->setUploadLengthAtStartup(allTimeUploadLength);
|
||||
delete [] savedBitfield;
|
||||
savedBitfield = 0;
|
||||
delete [] savedInfoHash;
|
||||
savedInfoHash = 0;
|
||||
fclose(file);
|
||||
} catch(string ex) {
|
||||
if(savedBitfield) {
|
||||
delete [] savedBitfield;
|
||||
}
|
||||
if(savedInfoHash) {
|
||||
delete [] savedInfoHash;
|
||||
}
|
||||
fclose(file);
|
||||
throw new DlAbortEx(EX_SEGMENT_FILE_READ,
|
||||
filename.c_str(), strerror(errno));
|
||||
}
|
||||
logger->info(MSG_LOADED_SEGMENT_FILE);
|
||||
}
|
||||
|
||||
void DefaultBtProgressInfoFile::removeFile() {
|
||||
if(exists()) {
|
||||
File f(filename);
|
||||
f.remove();
|
||||
}
|
||||
}
|
||||
|
||||
FILE* DefaultBtProgressInfoFile::openFile(const string& filename,
|
||||
const string& mode) const
|
||||
{
|
||||
FILE* file = fopen(filename.c_str(), mode.c_str());
|
||||
if(!file) {
|
||||
throw new DlAbortEx(EX_SEGMENT_FILE_OPEN,
|
||||
filename.c_str(), strerror(errno));
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
bool DefaultBtProgressInfoFile::exists() {
|
||||
File f(filename);
|
||||
if(f.isFile()) {
|
||||
logger->info(MSG_SEGMENT_FILE_EXISTS, filename.c_str());
|
||||
return true;
|
||||
} else {
|
||||
logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, filename.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
|
||||
#define _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
|
||||
|
||||
#include "BtProgressInfoFile.h"
|
||||
#include "BtContext.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "Logger.h"
|
||||
#include "Option.h"
|
||||
|
||||
class DefaultBtProgressInfoFile : public BtProgressInfoFile {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
const Option* option;
|
||||
Logger* logger;
|
||||
PieceStorageHandle pieceStorage;
|
||||
BtRuntimeHandle btRuntime;
|
||||
PeerStorageHandle peerStorage;
|
||||
string filename;
|
||||
|
||||
FILE* openFile(const string& filename, const string& mode) const;
|
||||
public:
|
||||
DefaultBtProgressInfoFile(const BtContextHandle& btContext,
|
||||
const Option* option);
|
||||
virtual ~DefaultBtProgressInfoFile();
|
||||
|
||||
void setBtRuntime(const BtRuntimeHandle& btRuntime) {
|
||||
this->btRuntime = btRuntime;
|
||||
}
|
||||
BtRuntimeHandle getBtRuntime() const { return btRuntime; }
|
||||
|
||||
void setPieceStorage(const PieceStorageHandle& pieceStorage) {
|
||||
this->pieceStorage = pieceStorage;
|
||||
}
|
||||
PieceStorageHandle getPieceStorage() const { return pieceStorage; }
|
||||
|
||||
void setPeerStorage(const PeerStorageHandle& peerStorage) {
|
||||
this->peerStorage = peerStorage;
|
||||
}
|
||||
PeerStorageHandle getPeerStorage() const { return peerStorage; }
|
||||
|
||||
virtual void setFilename(const string& filename) {
|
||||
this->filename = filename;
|
||||
}
|
||||
virtual string getFilename() { return filename; }
|
||||
|
||||
virtual bool exists();
|
||||
|
||||
virtual void save();
|
||||
|
||||
virtual void load();
|
||||
|
||||
virtual void removeFile();
|
||||
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_BT_PROGRESS_INFO_FILE_H_
|
|
@ -0,0 +1,174 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultPeerStorage.h"
|
||||
#include "LogFactory.h"
|
||||
#include "BtRegistry.h"
|
||||
|
||||
extern PeerHandle nullPeer;
|
||||
|
||||
DefaultPeerStorage::DefaultPeerStorage(BtContextHandle btContext,
|
||||
const Option* option):
|
||||
btContext(btContext),
|
||||
option(option),
|
||||
maxPeerListSize(MAX_PEER_LIST_SIZE),
|
||||
peerEntryIdCounter(0),
|
||||
btRuntime(BT_RUNTIME(btContext))
|
||||
{
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
DefaultPeerStorage::~DefaultPeerStorage() {}
|
||||
|
||||
bool DefaultPeerStorage::addPeer(const PeerHandle& peer) {
|
||||
Peers::iterator itr = find(peers.begin(), peers.end(), peer);
|
||||
if(itr == peers.end()) {
|
||||
if(peers.size() >= (size_t)maxPeerListSize) {
|
||||
deleteUnusedPeer(peers.size()-maxPeerListSize+1);
|
||||
}
|
||||
++peerEntryIdCounter;
|
||||
peer->entryId = peerEntryIdCounter;
|
||||
peers.push_back(peer);
|
||||
return true;
|
||||
} else {
|
||||
const PeerHandle& peer = *itr;
|
||||
if(peer->error >= MAX_PEER_ERROR || peer->cuid != 0) {
|
||||
return false;
|
||||
} else {
|
||||
*itr = peer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultPeerStorage::addPeer(const Peers& peers) {
|
||||
for(Peers::const_iterator itr = peers.begin();
|
||||
itr != peers.end(); itr++) {
|
||||
const PeerHandle& peer = *itr;
|
||||
if(addPeer(peer)) {
|
||||
logger->debug("Adding peer %s:%d",
|
||||
peer->ipaddr.c_str(), peer->port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Peers& DefaultPeerStorage::getPeers() {
|
||||
return peers;
|
||||
}
|
||||
|
||||
class FindFinePeer {
|
||||
public:
|
||||
bool operator()(const PeerHandle& peer) const {
|
||||
return peer->cuid == 0 && peer->error < MAX_PEER_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
PeerHandle DefaultPeerStorage::getUnusedPeer() {
|
||||
Peers::const_iterator itr = find_if(peers.begin(), peers.end(),
|
||||
FindFinePeer());
|
||||
if(itr == peers.end()) {
|
||||
return nullPeer;
|
||||
} else {
|
||||
return *itr;
|
||||
}
|
||||
}
|
||||
|
||||
class FindPeer {
|
||||
private:
|
||||
string ipaddr;
|
||||
int port;
|
||||
public:
|
||||
FindPeer(const string& ipaddr, int port):ipaddr(ipaddr), port(port) {}
|
||||
|
||||
bool operator()(const PeerHandle& peer) const {
|
||||
return ipaddr == peer->ipaddr && port == peer->port;
|
||||
}
|
||||
};
|
||||
|
||||
PeerHandle DefaultPeerStorage::getPeer(const string& ipaddr,
|
||||
int port) const {
|
||||
Peers::const_iterator itr = find_if(peers.begin(), peers.end(),
|
||||
FindPeer(ipaddr, port));
|
||||
if(itr == peers.end()) {
|
||||
return nullPeer;
|
||||
} else {
|
||||
return *itr;
|
||||
}
|
||||
}
|
||||
|
||||
int DefaultPeerStorage::countPeer() const {
|
||||
return peers.size();
|
||||
}
|
||||
|
||||
bool DefaultPeerStorage::isPeerAvailable() {
|
||||
return getUnusedPeer() != nullPeer;
|
||||
}
|
||||
|
||||
Peers DefaultPeerStorage::getActivePeers() {
|
||||
Peers activePeers;
|
||||
for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
|
||||
PeerHandle& peer = *itr;
|
||||
if(peer->isActive()) {
|
||||
activePeers.push_back(peer);
|
||||
}
|
||||
}
|
||||
return activePeers;
|
||||
}
|
||||
|
||||
TransferStat DefaultPeerStorage::calculateStat() {
|
||||
TransferStat stat;
|
||||
Peers activePeers = getActivePeers();
|
||||
for(Peers::iterator itr = activePeers.begin();
|
||||
itr != activePeers.end(); itr++) {
|
||||
PeerHandle& peer = *itr;
|
||||
stat.downloadSpeed += peer->calculateDownloadSpeed();
|
||||
stat.uploadSpeed += peer->calculateUploadSpeed();
|
||||
stat.sessionDownloadLength += peer->getSessionDownloadLength();
|
||||
stat.sessionUploadLength += peer->getSessionUploadLength();
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
void DefaultPeerStorage::deleteUnusedPeer(int delSize) {
|
||||
for(Peers::iterator itr = peers.begin();
|
||||
itr != peers.end() && delSize > 0;) {
|
||||
const PeerHandle& p = *itr;
|
||||
if(p->cuid == 0) {
|
||||
itr = peers.erase(itr);
|
||||
delSize--;
|
||||
} else {
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_PEER_STORAGE_H_
|
||||
#define _D_DEFAULT_PEER_STORAGE_H_
|
||||
|
||||
#include "PeerStorage.h"
|
||||
#include "BtContext.h"
|
||||
#include "Option.h"
|
||||
#include "Logger.h"
|
||||
#include "BtRuntime.h"
|
||||
|
||||
#define MAX_PEER_LIST_SIZE 100
|
||||
#define MAX_PEER_ERROR 5
|
||||
|
||||
class DefaultPeerStorage : public PeerStorage {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
const Option* option;
|
||||
Peers peers;
|
||||
int maxPeerListSize;
|
||||
int peerEntryIdCounter;
|
||||
Logger* logger;
|
||||
BtRuntimeHandle btRuntime;
|
||||
public:
|
||||
DefaultPeerStorage(BtContextHandle btContext, const Option* option);
|
||||
virtual ~DefaultPeerStorage();
|
||||
|
||||
void setBtRuntime(const BtRuntimeHandle& btRuntime) {
|
||||
this->btRuntime = btRuntime;
|
||||
}
|
||||
BtRuntimeHandle getBtRuntime() const { return btRuntime; }
|
||||
|
||||
virtual bool addPeer(const PeerHandle& peer);
|
||||
|
||||
int countPeer() const;
|
||||
|
||||
virtual PeerHandle getUnusedPeer();
|
||||
|
||||
PeerHandle getPeer(const string& ipaddr, int port) const;
|
||||
|
||||
virtual void addPeer(const Peers& peers);
|
||||
|
||||
virtual const Peers& getPeers();
|
||||
|
||||
virtual bool isPeerAvailable();
|
||||
|
||||
virtual Peers getActivePeers();
|
||||
|
||||
virtual TransferStat calculateStat();
|
||||
|
||||
void setMaxPeerListSize(int size) { this->maxPeerListSize = size; }
|
||||
|
||||
int getMaxPeerListSize() const { return maxPeerListSize; }
|
||||
|
||||
void deleteUnusedPeer(int delSize);
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_PEER_STORAGE_H_
|
|
@ -0,0 +1,433 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "DefaultPieceStorage.h"
|
||||
#include "LogFactory.h"
|
||||
#include "prefs.h"
|
||||
#include "DirectDiskAdaptor.h"
|
||||
#include "MultiDiskAdaptor.h"
|
||||
#include "CopyDiskAdaptor.h"
|
||||
#include "DefaultDiskWriter.h"
|
||||
#include "MultiDiskWriter.h"
|
||||
#include "PreAllocationDiskWriter.h"
|
||||
#include "DlAbortEx.h"
|
||||
|
||||
DefaultPieceStorage::DefaultPieceStorage(BtContextHandle btContext, const Option* option):
|
||||
btContext(btContext),
|
||||
endGamePieceNum(END_GAME_PIECE_NUM),
|
||||
option(option)
|
||||
{
|
||||
bitfieldMan = new BitfieldMan(btContext->getPieceLength(),
|
||||
btContext->getTotalLength());
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
DefaultPieceStorage::~DefaultPieceStorage() {
|
||||
delete bitfieldMan;
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::hasMissingPiece(const PeerHandle& peer) {
|
||||
return bitfieldMan->hasMissingPiece(peer->getBitfield(),
|
||||
peer->getBitfieldLength());
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::isEndGame() {
|
||||
return bitfieldMan->countMissingBlock() <= endGamePieceNum;
|
||||
}
|
||||
|
||||
int DefaultPieceStorage::getMissingPieceIndex(const PeerHandle& peer) {
|
||||
int index = -1;
|
||||
if(isEndGame()) {
|
||||
index = bitfieldMan->getMissingIndex(peer->getBitfield(),
|
||||
peer->getBitfieldLength());
|
||||
} else {
|
||||
index = bitfieldMan->getMissingUnusedIndex(peer->getBitfield(),
|
||||
peer->getBitfieldLength());
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
Piece DefaultPieceStorage::checkOutPiece(int index) {
|
||||
if(index == -1) {
|
||||
return Piece::nullPiece;
|
||||
}
|
||||
bitfieldMan->setUseBit(index);
|
||||
|
||||
Piece piece = findUsedPiece(index);
|
||||
if(Piece::isNull(piece)) {
|
||||
Piece piece(index, bitfieldMan->getBlockLength(index));
|
||||
addUsedPiece(piece);
|
||||
return piece;
|
||||
} else {
|
||||
return piece;
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::addUsedPiece(const Piece& piece) {
|
||||
// TODO ? if nullPiece
|
||||
usedPieces.push_back(piece);
|
||||
}
|
||||
|
||||
class FindPiece {
|
||||
private:
|
||||
int index;
|
||||
public:
|
||||
FindPiece(int index):index(index) {}
|
||||
|
||||
bool operator()(const Piece& piece) {
|
||||
return piece.getIndex() == index;
|
||||
}
|
||||
};
|
||||
|
||||
Piece DefaultPieceStorage::findUsedPiece(int index) const {
|
||||
Pieces::const_iterator itr = find_if(usedPieces.begin(),
|
||||
usedPieces.end(),
|
||||
FindPiece(index));
|
||||
if(itr == usedPieces.end()) {
|
||||
return Piece::nullPiece;
|
||||
} else {
|
||||
return *itr;
|
||||
}
|
||||
}
|
||||
|
||||
Piece DefaultPieceStorage::getMissingPiece(const PeerHandle& peer) {
|
||||
int index = getMissingPieceIndex(peer);
|
||||
return checkOutPiece(index);
|
||||
}
|
||||
|
||||
int DefaultPieceStorage::getMissingFastPieceIndex(const PeerHandle& peer) {
|
||||
int index = -1;
|
||||
if(peer->isFastExtensionEnabled() && peer->countFastSet() > 0) {
|
||||
BitfieldMan tempBitfield(bitfieldMan->getBlockLength(),
|
||||
bitfieldMan->getTotalLength());
|
||||
for(Integers::const_iterator itr = peer->getFastSet().begin();
|
||||
itr != peer->getFastSet().end(); itr++) {
|
||||
if(!bitfieldMan->isBitSet(index) && peer->hasPiece(*itr)) {
|
||||
tempBitfield.setBit(*itr);
|
||||
}
|
||||
}
|
||||
if(isEndGame()) {
|
||||
index = bitfieldMan->getMissingIndex(tempBitfield.getBitfield(),
|
||||
tempBitfield.getBitfieldLength());
|
||||
} else {
|
||||
index = bitfieldMan->getMissingUnusedIndex(tempBitfield.getBitfield(),
|
||||
tempBitfield.getBitfieldLength());
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
Piece DefaultPieceStorage::getMissingFastPiece(const PeerHandle& peer) {
|
||||
int index = getMissingFastPieceIndex(peer);
|
||||
return checkOutPiece(index);
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::deleteUsedPiece(const Piece& piece) {
|
||||
if(Piece::isNull(piece)) {
|
||||
return;
|
||||
}
|
||||
Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(), piece);
|
||||
if(itr != usedPieces.end()) {
|
||||
usedPieces.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::reduceUsedPieces(int delMax) {
|
||||
int toDelete = usedPieces.size()-delMax;
|
||||
if(toDelete <= 0) {
|
||||
return;
|
||||
}
|
||||
int fillRate = 10;
|
||||
while(fillRate < 50) {
|
||||
int deleted = deleteUsedPiecesByFillRate(fillRate, toDelete);
|
||||
if(deleted == 0) {
|
||||
break;
|
||||
}
|
||||
toDelete -= deleted;
|
||||
fillRate += 10;
|
||||
}
|
||||
}
|
||||
|
||||
int DefaultPieceStorage::deleteUsedPiecesByFillRate(int fillRate,
|
||||
int toDelete) {
|
||||
int deleted = 0;
|
||||
for(Pieces::iterator itr = usedPieces.begin();
|
||||
itr != usedPieces.end() && deleted < toDelete;) {
|
||||
Piece& piece = *itr;
|
||||
if(!bitfieldMan->isUseBitSet(piece.getIndex()) &&
|
||||
piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) {
|
||||
logger->debug("Deleting used piece index=%d, fillRate(%%)=%d<=%d",
|
||||
piece.getIndex(),
|
||||
(piece.countCompleteBlock()*100)/piece.countBlock(),
|
||||
fillRate);
|
||||
itr = usedPieces.erase(itr);
|
||||
deleted++;
|
||||
} else {
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::completePiece(const Piece& piece) {
|
||||
if(Piece::isNull(piece)) {
|
||||
return;
|
||||
}
|
||||
deleteUsedPiece(piece);
|
||||
if(!isEndGame()) {
|
||||
reduceUsedPieces(100);
|
||||
}
|
||||
if(downloadFinished()) {
|
||||
return;
|
||||
}
|
||||
bitfieldMan->setBit(piece.getIndex());
|
||||
bitfieldMan->unsetUseBit(piece.getIndex());
|
||||
if(downloadFinished()) {
|
||||
diskAdaptor->onDownloadComplete();
|
||||
if(isSelectiveDownloadingMode()) {
|
||||
logger->notice(_("Download of selected files was complete."));
|
||||
finishSelectiveDownloadingMode();
|
||||
} else {
|
||||
logger->info(_("The download was complete."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::isSelectiveDownloadingMode() {
|
||||
return bitfieldMan->isFilterEnabled();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::finishSelectiveDownloadingMode() {
|
||||
bitfieldMan->clearFilter();
|
||||
diskAdaptor->addAllDownloadEntry();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::cancelPiece(const Piece& piece) {
|
||||
if(Piece::isNull(piece)) {
|
||||
return;
|
||||
}
|
||||
updatePiece(piece);
|
||||
bitfieldMan->unsetUseBit(piece.getIndex());
|
||||
if(!isEndGame()) {
|
||||
if(piece.countCompleteBlock() == 0) {
|
||||
deleteUsedPiece(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::updatePiece(const Piece& piece) {
|
||||
if(Piece::isNull(piece)) {
|
||||
return;
|
||||
}
|
||||
Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
|
||||
piece);
|
||||
if(itr != usedPieces.end()) {
|
||||
*itr = piece;
|
||||
}
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::syncPiece(Piece& piece) {
|
||||
if(Piece::isNull(piece)) {
|
||||
return;
|
||||
}
|
||||
Pieces::iterator itr = find(usedPieces.begin(), usedPieces.end(),
|
||||
piece);
|
||||
if(itr != usedPieces.end()) {
|
||||
piece = *itr;
|
||||
return;
|
||||
} else {
|
||||
// hasPiece(piece.getIndex()) is true, then set all bit of
|
||||
// piece.bitfield to 1
|
||||
if(hasPiece(piece.getIndex())) {
|
||||
piece.setAllBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultPieceStorage::hasPiece(int index) {
|
||||
return bitfieldMan->isBitSet(index);
|
||||
}
|
||||
|
||||
long long int DefaultPieceStorage::getTotalLength() {
|
||||
return bitfieldMan->getTotalLength();
|
||||
}
|
||||
|
||||
long long int DefaultPieceStorage::getFilteredTotalLength() {
|
||||
return bitfieldMan->getFilteredTotalLength();
|
||||
}
|
||||
|
||||
long long int DefaultPieceStorage::getCompletedLength() {
|
||||
return bitfieldMan->getCompletedLength();
|
||||
}
|
||||
|
||||
long long int DefaultPieceStorage::getFilteredCompletedLength() {
|
||||
return bitfieldMan->getFilteredCompletedLength();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::setFileFilter(const Strings& filePaths) {
|
||||
if(btContext->getFileMode() != BtContext::MULTI || filePaths.empty()) {
|
||||
return;
|
||||
}
|
||||
diskAdaptor->removeAllDownloadEntry();
|
||||
for(Strings::const_iterator pitr = filePaths.begin();
|
||||
pitr != filePaths.end(); pitr++) {
|
||||
if(!diskAdaptor->addDownloadEntry(*pitr)) {
|
||||
throw new DlAbortEx("No such file entry %s", (*pitr).c_str());
|
||||
}
|
||||
FileEntryHandle fileEntry = diskAdaptor->getFileEntryFromPath(*pitr);
|
||||
bitfieldMan->addFilter(fileEntry->getOffset(), fileEntry->getLength());
|
||||
}
|
||||
bitfieldMan->enableFilter();
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) {
|
||||
Strings filePaths;
|
||||
const FileEntries& entries = diskAdaptor->getFileEntries();
|
||||
for(int i = 0; i < (int)entries.size(); i++) {
|
||||
if(find(fileIndexes.begin(), fileIndexes.end(), i+1) != fileIndexes.end()) {
|
||||
logger->debug("index=%d is %s", i+1, entries.at(i)->getPath().c_str());
|
||||
filePaths.push_back(entries.at(i)->getPath());
|
||||
}
|
||||
}
|
||||
setFileFilter(filePaths);
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::clearFileFilter() {
|
||||
bitfieldMan->clearFilter();
|
||||
diskAdaptor->addAllDownloadEntry();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
bool DefaultPieceStorage::downloadFinished() {
|
||||
return bitfieldMan->isAllBitSet();
|
||||
}
|
||||
|
||||
// not unittested
|
||||
void DefaultPieceStorage::initStorage() {
|
||||
if(diskAdaptor) {
|
||||
delete diskAdaptor;
|
||||
diskAdaptor = 0;
|
||||
}
|
||||
if(option->get(PREF_DIRECT_FILE_MAPPING) == V_TRUE) {
|
||||
if(btContext->getFileMode() == BtContext::SINGLE) {
|
||||
diskAdaptor = new DirectDiskAdaptor(new DefaultDiskWriter(btContext->getTotalLength()));
|
||||
} else {
|
||||
diskAdaptor = new MultiDiskAdaptor(new MultiDiskWriter(btContext->getPieceLength()));
|
||||
}
|
||||
} else {
|
||||
diskAdaptor = new CopyDiskAdaptor(new PreAllocationDiskWriter(btContext->getTotalLength()));
|
||||
((CopyDiskAdaptor*)diskAdaptor)->setTempFilename(btContext->getName()+".a2tmp");
|
||||
}
|
||||
string storeDir = option->get(PREF_DIR);
|
||||
if(storeDir == "") {
|
||||
storeDir = ".";
|
||||
}
|
||||
if(btContext->getFileMode() == BtContext::MULTI) {
|
||||
storeDir += "/"+btContext->getName();
|
||||
}
|
||||
diskAdaptor->setStoreDir(storeDir);
|
||||
diskAdaptor->setFileEntries(btContext->getFileEntries());
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::setBitfield(const unsigned char* bitfield,
|
||||
int bitfieldLength) {
|
||||
bitfieldMan->setBitfield(bitfield, bitfieldLength);
|
||||
}
|
||||
|
||||
int DefaultPieceStorage::getBitfieldLength() {
|
||||
return bitfieldMan->getBitfieldLength();
|
||||
}
|
||||
|
||||
const unsigned char* DefaultPieceStorage::getBitfield() {
|
||||
return bitfieldMan->getBitfield();
|
||||
}
|
||||
|
||||
DiskAdaptor* DefaultPieceStorage::getDiskAdaptor() {
|
||||
return diskAdaptor;
|
||||
}
|
||||
|
||||
int DefaultPieceStorage::getPieceLength(int index) {
|
||||
return bitfieldMan->getBlockLength(index);
|
||||
}
|
||||
|
||||
void DefaultPieceStorage::advertisePiece(int cuid, int index) {
|
||||
HaveEntry entry(cuid, index);
|
||||
haves.push_front(entry);
|
||||
}
|
||||
|
||||
Integers DefaultPieceStorage::getAdvertisedPieceIndexes(int myCuid,
|
||||
const Time& lastCheckTime) {
|
||||
Integers indexes;
|
||||
for(Haves::const_iterator itr = haves.begin(); itr != haves.end(); itr++) {
|
||||
const Haves::value_type& have = *itr;
|
||||
if(have.getCuid() == myCuid) {
|
||||
continue;
|
||||
}
|
||||
if(lastCheckTime.isNewer(have.getRegisteredTime())) {
|
||||
break;
|
||||
}
|
||||
indexes.push_back(have.getIndex());
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
class FindElapsedHave
|
||||
{
|
||||
private:
|
||||
int elapsed;
|
||||
public:
|
||||
FindElapsedHave(int elapsed):elapsed(elapsed) {}
|
||||
|
||||
bool operator()(const HaveEntry& have) {
|
||||
if(have.getRegisteredTime().elapsed(elapsed)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void DefaultPieceStorage::removeAdvertisedPiece(int elapsed) {
|
||||
Haves::iterator itr =
|
||||
find_if(haves.begin(), haves.end(), FindElapsedHave(elapsed));
|
||||
if(itr != haves.end()) {
|
||||
logger->debug("Removed %d have entries.", haves.end()-itr);
|
||||
haves.erase(itr, haves.end());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_DEFAULT_PIECE_STORAGE_H_
|
||||
#define _D_DEFAULT_PIECE_STORAGE_H_
|
||||
|
||||
#include "PieceStorage.h"
|
||||
#include "BtContext.h"
|
||||
#include "DiskAdaptor.h"
|
||||
#include "BitfieldMan.h"
|
||||
#include "Logger.h"
|
||||
#include "Option.h"
|
||||
#include "Piece.h"
|
||||
|
||||
#define END_GAME_PIECE_NUM 20
|
||||
|
||||
class HaveEntry {
|
||||
private:
|
||||
int cuid;
|
||||
int index;
|
||||
Time registeredTime;
|
||||
public:
|
||||
HaveEntry(int cuid, int index):
|
||||
cuid(cuid),
|
||||
index(index) {}
|
||||
|
||||
int getCuid() const { return cuid; }
|
||||
|
||||
int getIndex() const { return index; }
|
||||
|
||||
const Time& getRegisteredTime() const { return registeredTime; }
|
||||
};
|
||||
|
||||
typedef deque<HaveEntry> Haves;
|
||||
|
||||
class DefaultPieceStorage : public PieceStorage {
|
||||
private:
|
||||
BtContextHandle btContext;
|
||||
BitfieldMan* bitfieldMan;
|
||||
DiskAdaptor* diskAdaptor;
|
||||
Pieces usedPieces;
|
||||
int endGamePieceNum;
|
||||
Logger* logger;
|
||||
const Option* option;
|
||||
Haves haves;
|
||||
|
||||
int getMissingPieceIndex(const PeerHandle& peer);
|
||||
int getMissingFastPieceIndex(const PeerHandle& peer);
|
||||
Piece checkOutPiece(int index);
|
||||
void addUsedPiece(const Piece& piece);
|
||||
Piece findUsedPiece(int index) const;
|
||||
int deleteUsedPiecesByFillRate(int fillRate, int toDelete);
|
||||
void reduceUsedPieces(int delMax);
|
||||
void deleteUsedPiece(const Piece& piece);
|
||||
public:
|
||||
DefaultPieceStorage(BtContextHandle btContext, const Option* option);
|
||||
virtual ~DefaultPieceStorage();
|
||||
|
||||
virtual bool hasMissingPiece(const PeerHandle& peer);
|
||||
|
||||
virtual Piece getMissingPiece(const PeerHandle& peer);
|
||||
|
||||
virtual Piece getMissingFastPiece(const PeerHandle& peer);
|
||||
|
||||
virtual void completePiece(const Piece& piece);
|
||||
|
||||
virtual void cancelPiece(const Piece& piece);
|
||||
|
||||
virtual void updatePiece(const Piece& piece);
|
||||
|
||||
virtual void syncPiece(Piece& piece);
|
||||
|
||||
virtual bool hasPiece(int index);
|
||||
|
||||
virtual long long int getTotalLength();
|
||||
|
||||
virtual long long int getFilteredTotalLength();
|
||||
|
||||
virtual long long int getCompletedLength();
|
||||
|
||||
virtual long long int getFilteredCompletedLength();
|
||||
|
||||
virtual void initStorage();
|
||||
|
||||
virtual void setFileFilter(const Strings& filePaths);
|
||||
|
||||
virtual void setFileFilter(const Integers& fileIndexes);
|
||||
|
||||
virtual void clearFileFilter();
|
||||
|
||||
virtual bool downloadFinished();
|
||||
|
||||
virtual void setBitfield(const unsigned char* bitfield,
|
||||
int bitfieldLength);
|
||||
|
||||
virtual int getBitfieldLength();
|
||||
|
||||
virtual const unsigned char* getBitfield();
|
||||
|
||||
void setEndGamePieceNum(int num) {
|
||||
endGamePieceNum = num;
|
||||
}
|
||||
|
||||
int getEndGamePieceNum() const {
|
||||
return endGamePieceNum;
|
||||
}
|
||||
|
||||
virtual bool isSelectiveDownloadingMode();
|
||||
|
||||
virtual void finishSelectiveDownloadingMode();
|
||||
|
||||
virtual bool isEndGame();
|
||||
|
||||
virtual DiskAdaptor* getDiskAdaptor();
|
||||
|
||||
virtual int getPieceLength(int index);
|
||||
|
||||
virtual void advertisePiece(int cuid, int index);
|
||||
|
||||
virtual Integers getAdvertisedPieceIndexes(int myCuid,
|
||||
const Time& lastCheckTime);
|
||||
|
||||
virtual void removeAdvertisedPiece(int elapsed);
|
||||
|
||||
};
|
||||
|
||||
#endif // _D_DEFAULT_PIECE_STORAGE_H_
|
|
@ -54,4 +54,5 @@ bool DelegatingPeerListProcessor::canHandle(const MetaEntry* peersEntry) const {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ DirectDiskAdaptor::DirectDiskAdaptor(DiskWriter* diskWriter):DiskAdaptor(diskWri
|
|||
DirectDiskAdaptor::~DirectDiskAdaptor() {}
|
||||
|
||||
string DirectDiskAdaptor::getFilePath() const {
|
||||
return storeDir+"/"+fileEntries.front().path;
|
||||
return storeDir+"/"+fileEntries.front()->getPath();
|
||||
}
|
||||
|
||||
void DirectDiskAdaptor::onDownloadComplete() {
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
|
||||
Directory::Directory(const string& name):name(name) {}
|
||||
|
||||
Directory::Directory() {}
|
||||
|
||||
Directory::~Directory() {
|
||||
for(Files::iterator itr = files.begin(); itr != files.end(); itr++) {
|
||||
delete *itr;
|
||||
|
@ -49,6 +51,9 @@ Directory::~Directory() {
|
|||
}
|
||||
|
||||
void Directory::createDir(const string& parentDir, bool recursive) const {
|
||||
if(name.size() == 0) {
|
||||
return;
|
||||
}
|
||||
string path = parentDir+"/"+name;
|
||||
File f(path);
|
||||
if(f.exists()) {
|
||||
|
|
|
@ -48,10 +48,13 @@ private:
|
|||
Files files;
|
||||
public:
|
||||
Directory(const string& name);
|
||||
Directory();
|
||||
~Directory();
|
||||
|
||||
void createDir(const string& parentDir, bool recursive) const;
|
||||
void addFile(Directory* directory);
|
||||
};
|
||||
|
||||
typedef SharedHandle<Directory> DirectoryHandle;
|
||||
|
||||
#endif // _D_DIRECTORY_H_
|
||||
|
|
|
@ -36,15 +36,12 @@
|
|||
#include "DlAbortEx.h"
|
||||
#include "LogFactory.h"
|
||||
|
||||
DiskAdaptor::DiskAdaptor(DiskWriter* diskWriter):diskWriter(diskWriter), topDir(NULL) {
|
||||
DiskAdaptor::DiskAdaptor(DiskWriter* diskWriter):diskWriter(diskWriter) {
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
DiskAdaptor::~DiskAdaptor() {
|
||||
delete diskWriter;
|
||||
if(topDir != NULL) {
|
||||
delete topDir;
|
||||
}
|
||||
}
|
||||
|
||||
void DiskAdaptor::openFile() {
|
||||
|
@ -75,10 +72,10 @@ string DiskAdaptor::sha1Sum(long long int offset, long long int length) {
|
|||
return diskWriter->sha1Sum(offset, length);
|
||||
}
|
||||
|
||||
FileEntry DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const {
|
||||
FileEntryHandle DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const {
|
||||
for(FileEntries::const_iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
if(itr->path == fileEntryPath) {
|
||||
if((*itr)->getPath() == fileEntryPath) {
|
||||
return *itr;
|
||||
}
|
||||
}
|
||||
|
@ -88,8 +85,8 @@ FileEntry DiskAdaptor::getFileEntryFromPath(const string& fileEntryPath) const {
|
|||
bool DiskAdaptor::addDownloadEntry(const string& fileEntryPath) {
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
if(itr->path == fileEntryPath) {
|
||||
itr->requested = true;
|
||||
if((*itr)->getPath() == fileEntryPath) {
|
||||
(*itr)->setRequested(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -100,20 +97,20 @@ bool DiskAdaptor::addDownloadEntry(int index) {
|
|||
if(fileEntries.size() <= (unsigned int)index) {
|
||||
return false;
|
||||
}
|
||||
fileEntries.at(index).requested = true;
|
||||
fileEntries.at(index)->setRequested(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiskAdaptor::addAllDownloadEntry() {
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
itr->requested = true;
|
||||
(*itr)->setRequested(true);
|
||||
}
|
||||
}
|
||||
|
||||
void DiskAdaptor::removeAllDownloadEntry() {
|
||||
for(FileEntries::iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
itr->requested = false;
|
||||
(*itr)->setRequested(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@
|
|||
#include "Directory.h"
|
||||
#include "DiskWriter.h"
|
||||
#include "Logger.h"
|
||||
#include "FileEntry.h"
|
||||
|
||||
class DiskAdaptor {
|
||||
protected:
|
||||
DiskWriter* diskWriter;
|
||||
string storeDir;
|
||||
FileEntries fileEntries;
|
||||
const Directory* topDir;
|
||||
const Logger* logger;
|
||||
virtual string getFilePath() const = 0;
|
||||
public:
|
||||
|
@ -66,7 +66,9 @@ public:
|
|||
void setFileEntries(const FileEntries& fileEntries) {
|
||||
this->fileEntries = fileEntries;
|
||||
}
|
||||
FileEntry getFileEntryFromPath(const string& fileEntryPath) const;
|
||||
|
||||
FileEntryHandle getFileEntryFromPath(const string& fileEntryPath) const;
|
||||
|
||||
const FileEntries& getFileEntries() const { return fileEntries; }
|
||||
|
||||
bool addDownloadEntry(const string& fileEntryPath);
|
||||
|
@ -75,15 +77,8 @@ public:
|
|||
void removeAllDownloadEntry();
|
||||
|
||||
void setStoreDir(const string& storeDir) { this->storeDir = storeDir; }
|
||||
string getStoreDir() const { return this->storeDir; }
|
||||
|
||||
void setTopDir(const Directory* dirctory) {
|
||||
if(this->topDir != NULL) {
|
||||
delete topDir;
|
||||
}
|
||||
this->topDir = dirctory;
|
||||
}
|
||||
const Directory* getTopDir() const { return this->topDir; }
|
||||
string getStoreDir() const { return this->storeDir; }
|
||||
};
|
||||
|
||||
#endif // _D_DISK_ADAPTOR_H_
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
# include "UnionSeedCriteria.h"
|
||||
# include "TimeSeedCriteria.h"
|
||||
# include "ShareRatioSeedCriteria.h"
|
||||
# include "DefaultPieceStorage.h"
|
||||
# include "DefaultPeerStorage.h"
|
||||
# include "DefaultBtAnnounce.h"
|
||||
# include "DefaultBtProgressInfoFile.h"
|
||||
#endif // ENABLE_BITTORRENT
|
||||
|
||||
ConsoleDownloadEngine*
|
||||
|
@ -76,8 +80,8 @@ DownloadEngineFactory::newConsoleEngine(const Option* op,
|
|||
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
TorrentConsoleDownloadEngine*
|
||||
DownloadEngineFactory::newTorrentConsoleEngine(const Option* op,
|
||||
const string& torrentFile,
|
||||
DownloadEngineFactory::newTorrentConsoleEngine(const BtContextHandle& btContext,
|
||||
const Option* op,
|
||||
const Strings& targetFiles)
|
||||
{
|
||||
TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine();
|
||||
|
@ -86,19 +90,44 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op,
|
|||
te->segmentMan = new SegmentMan();
|
||||
te->segmentMan->diskWriter = byteArrayDiskWriter;
|
||||
te->segmentMan->option = op;
|
||||
te->torrentMan = new TorrentMan();
|
||||
te->torrentMan->setStoreDir(op->get(PREF_DIR));
|
||||
te->torrentMan->option = op;
|
||||
BtRuntimeHandle btRuntime(new BtRuntime());
|
||||
BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime);
|
||||
|
||||
PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, op));
|
||||
BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), pieceStorage);
|
||||
|
||||
PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, op));
|
||||
BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage);
|
||||
|
||||
BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, op));
|
||||
BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce);
|
||||
btAnnounce->shuffleAnnounce();
|
||||
|
||||
BtProgressInfoFileHandle btProgressInfoFile(new DefaultBtProgressInfoFile(btContext, op));
|
||||
BtRegistry::registerBtProgressInfoFile(btContext->getInfoHashAsString(),
|
||||
btProgressInfoFile);
|
||||
|
||||
te->setBtContext(btContext);
|
||||
// initialize file storage
|
||||
pieceStorage->initStorage();
|
||||
if(btProgressInfoFile->exists()) {
|
||||
// load .aria2 file if it exists.
|
||||
btProgressInfoFile->load();
|
||||
pieceStorage->getDiskAdaptor()->openExistingFile();
|
||||
} else {
|
||||
pieceStorage->getDiskAdaptor()->initAndOpenFile();
|
||||
}
|
||||
|
||||
Integers selectIndexes;
|
||||
Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes);
|
||||
if(selectIndexes.size()) {
|
||||
te->torrentMan->setup(torrentFile, selectIndexes);
|
||||
pieceStorage->setFileFilter(selectIndexes);
|
||||
} else {
|
||||
te->torrentMan->setup(torrentFile, targetFiles);
|
||||
pieceStorage->setFileFilter(targetFiles);
|
||||
}
|
||||
|
||||
PeerListenCommand* listenCommand =
|
||||
new PeerListenCommand(te->torrentMan->getNewCuid(), te);
|
||||
new PeerListenCommand(btRuntime->getNewCuid(), te, btContext);
|
||||
int port;
|
||||
int listenPort = op->getAsInt(PREF_LISTEN_PORT);
|
||||
if(listenPort == -1) {
|
||||
|
@ -110,31 +139,39 @@ DownloadEngineFactory::newTorrentConsoleEngine(const Option* op,
|
|||
printf(_("Errors occurred while binding port.\n"));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
te->torrentMan->setPort(port);
|
||||
btRuntime->setListenPort(port);
|
||||
te->commands.push_back(listenCommand);
|
||||
|
||||
te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(),
|
||||
te));
|
||||
te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(),
|
||||
te));
|
||||
te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(),
|
||||
te->commands.push_back(new TrackerWatcherCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext));
|
||||
te->commands.push_back(new TrackerUpdateCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext));
|
||||
te->commands.push_back(new TorrentAutoSaveCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext,
|
||||
op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
|
||||
te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(),
|
||||
te, 10));
|
||||
te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(),
|
||||
te, 10));
|
||||
te->commands.push_back(new PeerChokeCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext,
|
||||
10));
|
||||
te->commands.push_back(new HaveEraseCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext,
|
||||
10));
|
||||
|
||||
SharedHandle<UnionSeedCriteria> unionCri = new UnionSeedCriteria();
|
||||
if(op->defined(PREF_SEED_TIME)) {
|
||||
unionCri->addSeedCriteria(new TimeSeedCriteria(op->getAsInt(PREF_SEED_TIME)*60));
|
||||
}
|
||||
if(op->defined(PREF_SEED_RATIO)) {
|
||||
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), te->torrentMan));
|
||||
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(op->getAsDouble(PREF_SEED_RATIO), btContext));
|
||||
}
|
||||
if(unionCri->getSeedCriterion().size() > 0) {
|
||||
te->commands.push_back(new SeedCheckCommand(te->torrentMan->getNewCuid(),
|
||||
te->commands.push_back(new SeedCheckCommand(btRuntime->getNewCuid(),
|
||||
te,
|
||||
btContext,
|
||||
unionCri));
|
||||
}
|
||||
return te;
|
||||
|
|
|
@ -50,8 +50,8 @@ public:
|
|||
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
static TorrentConsoleDownloadEngine*
|
||||
newTorrentConsoleEngine(const Option* option,
|
||||
const string& torrentFile,
|
||||
newTorrentConsoleEngine(const BtContextHandle& btContext,
|
||||
const Option* option,
|
||||
const Strings& targetFiles);
|
||||
#endif // ENABLE_BITTORRENT
|
||||
};
|
||||
|
|
28
src/File.cc
28
src/File.cc
|
@ -33,6 +33,7 @@
|
|||
*/
|
||||
/* copyright --> */
|
||||
#include "File.h"
|
||||
#include "Util.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
@ -83,3 +84,30 @@ long long int File::size() {
|
|||
}
|
||||
return fstat.st_size;
|
||||
}
|
||||
|
||||
bool File::mkdirs() {
|
||||
if(isDir()) {
|
||||
return false;
|
||||
}
|
||||
Strings dirs;
|
||||
Util::slice(dirs, name, '/');
|
||||
if(!dirs.size()) {
|
||||
return true;
|
||||
}
|
||||
string accDir;
|
||||
if(Util::startsWith(name, "/")) {
|
||||
accDir = "/";
|
||||
}
|
||||
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR;
|
||||
for(Strings::const_iterator itr = dirs.begin(); itr != dirs.end();
|
||||
itr++, accDir += "/") {
|
||||
accDir += *itr;
|
||||
if(File(accDir).isDir()) {
|
||||
continue;
|
||||
}
|
||||
if(mkdir(accDir.c_str(), mode) == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,15 @@ public:
|
|||
*/
|
||||
bool remove();
|
||||
|
||||
/**
|
||||
* Creates the directory denoted by name.
|
||||
* This method creates complete directory structure.
|
||||
* Returns true if the directory is created successfully, otherwise returns
|
||||
* false.
|
||||
* If the directory already exists, then returns false.
|
||||
*/
|
||||
bool mkdirs();
|
||||
|
||||
long long int size();
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "FileEntry.h"
|
||||
#include "File.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include <libgen.h>
|
||||
|
||||
FileEntry::FileEntry(const string& path,
|
||||
long long int length,
|
||||
long long int offset):
|
||||
path(path), length(length), offset(offset),
|
||||
extracted(false), requested(true) {}
|
||||
|
||||
FileEntry::~FileEntry() {}
|
||||
|
||||
void FileEntry::setupDir(const string& parentDir) {
|
||||
string absPath = parentDir+"/"+path;
|
||||
char* temp = strdup(absPath.c_str());
|
||||
string dir = string(dirname(temp));
|
||||
free(temp);
|
||||
if(!dir.size()) {
|
||||
return;
|
||||
}
|
||||
File f(dir);
|
||||
if(f.isDir()) {
|
||||
// nothing to do
|
||||
} else if(f.exists()) {
|
||||
throw new DlAbortEx("%s is not a directory.", dir.c_str());
|
||||
} else if(!f.mkdirs()) {
|
||||
throw new DlAbortEx("Failed to create directory %s.", dir.c_str());
|
||||
}
|
||||
}
|
|
@ -38,18 +38,41 @@
|
|||
#include "common.h"
|
||||
|
||||
class FileEntry {
|
||||
public:
|
||||
private:
|
||||
string path;
|
||||
long long int length;
|
||||
long long int offset;
|
||||
bool extracted;
|
||||
bool requested;
|
||||
FileEntry(const string& path, long long int length, long long int offset):
|
||||
path(path), length(length), offset(offset),
|
||||
extracted(false), requested(true) {}
|
||||
~FileEntry() {}
|
||||
public:
|
||||
FileEntry(const string& path, long long int length, long long int offset);
|
||||
|
||||
~FileEntry();
|
||||
|
||||
const string& getPath() const { return path; }
|
||||
|
||||
void setPath(const string& path) { this->path = path; }
|
||||
|
||||
long long int getLength() const { return length; }
|
||||
|
||||
void setLength(long long int length) { this->length = length; }
|
||||
|
||||
long long int getOffset() const { return offset; }
|
||||
|
||||
void setOffset(long long int offset) { this->offset = offset; }
|
||||
|
||||
bool isExtracted() const { return extracted; }
|
||||
|
||||
void setExtracted(bool flag) { this->extracted = flag; }
|
||||
|
||||
bool isRequested() const { return requested; }
|
||||
|
||||
void setRequested(bool flag) { this->requested = flag; }
|
||||
|
||||
void setupDir(const string& parentDir);
|
||||
};
|
||||
|
||||
typedef deque<FileEntry> FileEntries;
|
||||
typedef SharedHandle<FileEntry> FileEntryHandle;
|
||||
typedef deque<FileEntryHandle> FileEntries;
|
||||
|
||||
#endif // _D_FILE_ENTRY_H_
|
||||
|
|
|
@ -93,7 +93,7 @@ string HandshakeMessage::toString() const {
|
|||
|
||||
void HandshakeMessage::check() const {
|
||||
PeerMessageUtil::checkHandshake(this,
|
||||
peerInteraction->getTorrentMan()->getInfoHash());
|
||||
peerInteraction->getBtContext()->getInfoHash());
|
||||
}
|
||||
|
||||
bool HandshakeMessage::isFastExtensionSupported() const {
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#define _D_HANDSHAKE_MESSAGE_H_
|
||||
|
||||
#include "SimplePeerMessage.h"
|
||||
#include "TorrentMan.h"
|
||||
|
||||
#define PSTR "BitTorrent protocol"
|
||||
#define HANDSHAKE_MESSAGE_LENGTH 68
|
||||
|
|
|
@ -34,13 +34,21 @@
|
|||
/* copyright --> */
|
||||
#include "HaveEraseCommand.h"
|
||||
|
||||
HaveEraseCommand::HaveEraseCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval)
|
||||
:BtContextAwareCommand(cuid, btContext),
|
||||
e(e),
|
||||
interval(interval) {}
|
||||
|
||||
bool HaveEraseCommand::execute() {
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
if(cp.elapsed(interval)) {
|
||||
cp.reset();
|
||||
e->torrentMan->removeAdvertisedPiece(5);
|
||||
pieceStorage->removeAdvertisedPiece(5);
|
||||
}
|
||||
e->commands.push_back(this);
|
||||
return false;
|
||||
|
|
|
@ -35,19 +35,19 @@
|
|||
#ifndef _D_HAVE_ERASE_COMMAND_H_
|
||||
#define _D_HAVE_ERASE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
|
||||
class HaveEraseCommand : public Command {
|
||||
class HaveEraseCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
Time cp;
|
||||
int interval;
|
||||
public:
|
||||
HaveEraseCommand(int cuid, TorrentDownloadEngine* e, int interval)
|
||||
:Command(cuid),
|
||||
e(e),
|
||||
interval(interval) {}
|
||||
HaveEraseCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval);
|
||||
|
||||
virtual ~HaveEraseCommand() {}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ SRCS += MetaEntry.h\
|
|||
MetaFileUtil.cc MetaFileUtil.h\
|
||||
MetaEntryVisitor.h\
|
||||
ShaVisitor.cc ShaVisitor.h\
|
||||
TorrentMan.cc TorrentMan.h\
|
||||
PeerConnection.cc PeerConnection.h\
|
||||
PeerMessageUtil.cc PeerMessageUtil.h\
|
||||
PeerAbstractCommand.cc PeerAbstractCommand.h\
|
||||
|
@ -92,7 +91,7 @@ SRCS += MetaEntry.h\
|
|||
CopyDiskAdaptor.cc CopyDiskAdaptor.h\
|
||||
DirectDiskAdaptor.cc DirectDiskAdaptor.h\
|
||||
MultiDiskAdaptor.cc MultiDiskAdaptor.h\
|
||||
FileEntry.h\
|
||||
FileEntry.cc FileEntry.h\
|
||||
TrackerUpdateCommand.cc TrackerUpdateCommand.h\
|
||||
ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\
|
||||
PeerChokeCommand.cc PeerChokeCommand.h\
|
||||
|
@ -125,7 +124,21 @@ SRCS += MetaEntry.h\
|
|||
DefaultPeerListProcessor.cc DefaultPeerListProcessor.h\
|
||||
CompactPeerListProcessor.cc CompactPeerListProcessor.h\
|
||||
DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h\
|
||||
AnnounceList.h AnnounceList.cc
|
||||
AnnounceTier.h\
|
||||
AnnounceList.h AnnounceList.cc\
|
||||
BtContext.h\
|
||||
DefaultBtContext.cc DefaultBtContext.h\
|
||||
PieceStorage.h\
|
||||
DefaultPieceStorage.cc DefaultPieceStorage.h\
|
||||
PeerService.h\
|
||||
DefaultPeerStorage.cc DefaultPeerStorage.h\
|
||||
BtAnnounce.h\
|
||||
DefaultBtAnnounce.cc DefaultBtAnnounce.h\
|
||||
BtRegistry.cc BtRegistry.h\
|
||||
BtRuntime.h\
|
||||
BtProgressInfoFile.h\
|
||||
DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
|
||||
BtContextAwareCommand.cc BtContextAwareCommand.h
|
||||
endif # ENABLE_BITTORRENT
|
||||
|
||||
if ENABLE_METALINK
|
||||
|
|
|
@ -46,7 +46,6 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
|||
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.cc MetaFileUtil.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ MetaEntryVisitor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ ShaVisitor.cc ShaVisitor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ TorrentMan.cc TorrentMan.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerConnection.cc PeerConnection.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.cc PeerMessageUtil.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.cc PeerAbstractCommand.h\
|
||||
|
@ -69,7 +68,7 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
|||
@ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.cc CopyDiskAdaptor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.cc DirectDiskAdaptor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.cc MultiDiskAdaptor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ FileEntry.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ FileEntry.cc FileEntry.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.cc TrackerUpdateCommand.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.cc ByteArrayDiskWriter.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.cc PeerChokeCommand.h\
|
||||
|
@ -102,7 +101,21 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
|||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessor.cc DefaultPeerListProcessor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ CompactPeerListProcessor.cc CompactPeerListProcessor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DelegatingPeerListProcessor.cc DelegatingPeerListProcessor.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceList.h AnnounceList.cc
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceTier.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceList.h AnnounceList.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtContext.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.cc DefaultBtContext.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PieceStorage.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorage.cc DefaultPieceStorage.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerService.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.cc DefaultPeerStorage.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtAnnounce.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.cc DefaultBtAnnounce.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtRegistry.cc BtRegistry.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtRuntime.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtProgressInfoFile.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.cc DefaultBtProgressInfoFile.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.cc BtContextAwareCommand.h
|
||||
|
||||
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
||||
|
@ -172,10 +185,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
BitfieldMan.cc BitfieldMan.h NameResolver.cc NameResolver.h \
|
||||
MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \
|
||||
List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
|
||||
ShaVisitor.cc ShaVisitor.h TorrentMan.cc TorrentMan.h \
|
||||
PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \
|
||||
PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \
|
||||
PeerInitiateConnectionCommand.cc \
|
||||
ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \
|
||||
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
|
||||
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
|
||||
PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
|
||||
PeerInteractionCommand.h Peer.cc Peer.h \
|
||||
TorrentDownloadEngine.cc TorrentDownloadEngine.h \
|
||||
|
@ -189,11 +201,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
MultiDiskWriter.h DiskAdaptor.cc DiskAdaptor.h \
|
||||
CopyDiskAdaptor.cc CopyDiskAdaptor.h DirectDiskAdaptor.cc \
|
||||
DirectDiskAdaptor.h MultiDiskAdaptor.cc MultiDiskAdaptor.h \
|
||||
FileEntry.h TrackerUpdateCommand.cc TrackerUpdateCommand.h \
|
||||
ByteArrayDiskWriter.cc ByteArrayDiskWriter.h \
|
||||
PeerChokeCommand.cc PeerChokeCommand.h ChokeMessage.cc \
|
||||
ChokeMessage.h UnchokeMessage.cc UnchokeMessage.h \
|
||||
InterestedMessage.cc InterestedMessage.h \
|
||||
FileEntry.cc FileEntry.h TrackerUpdateCommand.cc \
|
||||
TrackerUpdateCommand.h ByteArrayDiskWriter.cc \
|
||||
ByteArrayDiskWriter.h PeerChokeCommand.cc PeerChokeCommand.h \
|
||||
ChokeMessage.cc ChokeMessage.h UnchokeMessage.cc \
|
||||
UnchokeMessage.h InterestedMessage.cc InterestedMessage.h \
|
||||
NotInterestedMessage.cc NotInterestedMessage.h HaveMessage.cc \
|
||||
HaveMessage.h BitfieldMessage.cc BitfieldMessage.h \
|
||||
RequestMessage.cc RequestMessage.h PieceMessage.cc \
|
||||
|
@ -211,9 +223,17 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
PeerListProcessor.h DefaultPeerListProcessor.cc \
|
||||
DefaultPeerListProcessor.h CompactPeerListProcessor.cc \
|
||||
CompactPeerListProcessor.h DelegatingPeerListProcessor.cc \
|
||||
DelegatingPeerListProcessor.h AnnounceList.h AnnounceList.cc \
|
||||
Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
|
||||
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
|
||||
DelegatingPeerListProcessor.h AnnounceTier.h AnnounceList.h \
|
||||
AnnounceList.cc BtContext.h DefaultBtContext.cc \
|
||||
DefaultBtContext.h PieceStorage.h DefaultPieceStorage.cc \
|
||||
DefaultPieceStorage.h PeerService.h DefaultPeerStorage.cc \
|
||||
DefaultPeerStorage.h BtAnnounce.h DefaultBtAnnounce.cc \
|
||||
DefaultBtAnnounce.h BtRegistry.cc BtRegistry.h BtRuntime.h \
|
||||
BtProgressInfoFile.h DefaultBtProgressInfoFile.cc \
|
||||
DefaultBtProgressInfoFile.h BtContextAwareCommand.cc \
|
||||
BtContextAwareCommand.h Metalinker.cc Metalinker.h \
|
||||
MetalinkEntry.cc MetalinkEntry.h MetalinkResource.cc \
|
||||
MetalinkResource.h MetalinkProcessor.h \
|
||||
Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \
|
||||
MetalinkRequestInfo.cc MetalinkRequestInfo.h
|
||||
@ENABLE_ASYNC_DNS_TRUE@am__objects_1 = NameResolver.$(OBJEXT)
|
||||
|
@ -221,7 +241,6 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
@ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ ShaVisitor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ TorrentMan.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerConnection.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.$(OBJEXT) \
|
||||
|
@ -243,6 +262,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
@ENABLE_BITTORRENT_TRUE@ CopyDiskAdaptor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DirectDiskAdaptor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ FileEntry.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ TrackerUpdateCommand.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriter.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PeerChokeCommand.$(OBJEXT) \
|
||||
|
@ -270,7 +290,14 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ CompactPeerListProcessor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DelegatingPeerListProcessor.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceList.$(OBJEXT)
|
||||
@ENABLE_BITTORRENT_TRUE@ AnnounceList.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtContext.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPieceStorage.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorage.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtAnnounce.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ BtRegistry.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ DefaultBtProgressInfoFile.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ BtContextAwareCommand.$(OBJEXT)
|
||||
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
||||
|
@ -598,6 +625,8 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMessage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtContextAwareCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtRegistry.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ByteArrayDiskWriter.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CancelMessage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChokeMessage.Po@am__quote@
|
||||
|
@ -608,8 +637,13 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBox.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CopyDiskAdaptor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Data.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounce.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContext.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFile.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DelegatingPeerListProcessor.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Dictionary.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirectDiskAdaptor.Po@am__quote@
|
||||
|
@ -620,6 +654,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileEntry.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpDownloadCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpInitiateConnectionCommand.Po@am__quote@
|
||||
|
@ -687,7 +722,6 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentMan.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentRequestInfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerUpdateCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@
|
||||
|
|
|
@ -46,14 +46,21 @@ string MultiDiskAdaptor::getFilePath() const {
|
|||
return storeDir;
|
||||
}
|
||||
|
||||
void MultiDiskAdaptor::mkdir() const {
|
||||
for(FileEntries::const_iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); itr++) {
|
||||
(*itr)->setupDir(storeDir);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiDiskAdaptor::openFile() {
|
||||
topDir->createDir(storeDir, true);
|
||||
mkdir();
|
||||
setDiskWriterFileEntries();
|
||||
DiskAdaptor::openFile();
|
||||
}
|
||||
|
||||
void MultiDiskAdaptor::initAndOpenFile() {
|
||||
topDir->createDir(storeDir, true);
|
||||
mkdir();
|
||||
setDiskWriterFileEntries();
|
||||
DiskAdaptor::initAndOpenFile();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
class MultiDiskAdaptor : public DiskAdaptor {
|
||||
private:
|
||||
void setDiskWriterFileEntries();
|
||||
void mkdir() const;
|
||||
protected:
|
||||
virtual string getFilePath() const;
|
||||
public:
|
||||
|
|
|
@ -68,7 +68,7 @@ void MultiDiskWriter::setFileEntries(const FileEntries& fileEntries) {
|
|||
void MultiDiskWriter::openFile(const string& filename) {
|
||||
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
|
||||
itr != diskWriterEntries.end(); itr++) {
|
||||
(*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry.path);
|
||||
(*itr)->diskWriter->openFile(filename+"/"+(*itr)->fileEntry->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ void MultiDiskWriter::openFile(const string& filename) {
|
|||
void MultiDiskWriter::initAndOpenFile(const string& filename) {
|
||||
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
|
||||
itr != diskWriterEntries.end(); itr++) {
|
||||
(*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry.path);
|
||||
(*itr)->diskWriter->initAndOpenFile(filename+"/"+(*itr)->fileEntry->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ void MultiDiskWriter::closeFile() {
|
|||
void MultiDiskWriter::openExistingFile(const string& filename) {
|
||||
for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
|
||||
itr != diskWriterEntries.end(); itr++) {
|
||||
(*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry.path);
|
||||
(*itr)->diskWriter->openExistingFile(filename+"/"+(*itr)->fileEntry->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int offset)
|
|||
writing = true;
|
||||
fileOffset = 0;
|
||||
} else {
|
||||
fileOffset -= (*itr)->fileEntry.length;
|
||||
fileOffset -= (*itr)->fileEntry->getLength();
|
||||
}
|
||||
}
|
||||
if(!writing) {
|
||||
|
@ -116,14 +116,14 @@ void MultiDiskWriter::writeData(const char* data, int len, long long int offset)
|
|||
}
|
||||
|
||||
bool MultiDiskWriter::isInRange(const DiskWriterEntry* entry, long long int offset) const {
|
||||
return entry->fileEntry.offset <= offset &&
|
||||
offset < entry->fileEntry.offset+entry->fileEntry.length;
|
||||
return entry->fileEntry->getOffset() <= offset &&
|
||||
offset < entry->fileEntry->getOffset()+entry->fileEntry->getLength();
|
||||
}
|
||||
|
||||
int MultiDiskWriter::calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const {
|
||||
int length;
|
||||
if(entry->fileEntry.length < fileOffset+rem) {
|
||||
length = entry->fileEntry.length-fileOffset;
|
||||
if(entry->fileEntry->getLength() < fileOffset+rem) {
|
||||
length = entry->fileEntry->getLength()-fileOffset;
|
||||
} else {
|
||||
length = rem;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ int MultiDiskWriter::readData(char* data, int len, long long int offset) {
|
|||
reading = true;
|
||||
fileOffset = 0;
|
||||
} else {
|
||||
fileOffset -= (*itr)->fileEntry.length;
|
||||
fileOffset -= (*itr)->fileEntry->getLength();
|
||||
}
|
||||
}
|
||||
if(!reading) {
|
||||
|
@ -187,7 +187,7 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) {
|
|||
reading = true;
|
||||
fileOffset = 0;
|
||||
} else {
|
||||
fileOffset -= (*itr)->fileEntry.length;
|
||||
fileOffset -= (*itr)->fileEntry->getLength();
|
||||
}
|
||||
}
|
||||
if(!reading) {
|
||||
|
|
|
@ -36,16 +36,16 @@
|
|||
#define _D_MULTI_DISK_WRITER_H_
|
||||
|
||||
#include "DefaultDiskWriter.h"
|
||||
#include "TorrentMan.h"
|
||||
#include "messageDigest.h"
|
||||
#include "FileEntry.h"
|
||||
|
||||
class DiskWriterEntry {
|
||||
public:
|
||||
FileEntry fileEntry;
|
||||
FileEntryHandle fileEntry;
|
||||
DiskWriter* diskWriter;
|
||||
public:
|
||||
DiskWriterEntry(const FileEntry& fileEntry):fileEntry(fileEntry) {
|
||||
diskWriter = new DefaultDiskWriter(this->fileEntry.length);
|
||||
DiskWriterEntry(const FileEntryHandle& fileEntry):fileEntry(fileEntry) {
|
||||
diskWriter = new DefaultDiskWriter(this->fileEntry->getLength());
|
||||
}
|
||||
~DiskWriterEntry() {
|
||||
delete diskWriter;
|
||||
|
|
14
src/Peer.h
14
src/Peer.h
|
@ -75,11 +75,12 @@ private:
|
|||
long long int sessionDownloadLength;
|
||||
int pieceLength;
|
||||
int latency;
|
||||
bool active;
|
||||
public:
|
||||
Peer(string ipaddr, int port, int pieceLength, long long int totalLength)
|
||||
:entryId(0), ipaddr(ipaddr), port(port), error(0),
|
||||
Peer(string ipaddr, int port, int pieceLength, long long int totalLength):
|
||||
entryId(0), ipaddr(ipaddr), port(port), error(0),
|
||||
sessionUploadLength(0), sessionDownloadLength(0),
|
||||
pieceLength(pieceLength)
|
||||
pieceLength(pieceLength), active(false)
|
||||
{
|
||||
resetStatus();
|
||||
this->bitfield = new BitfieldMan(pieceLength, totalLength);
|
||||
|
@ -148,10 +149,16 @@ public:
|
|||
|
||||
void activate() {
|
||||
peerStat.downloadStart();
|
||||
active = true;
|
||||
}
|
||||
|
||||
void deactivate() {
|
||||
peerStat.downloadStop();
|
||||
active = false;
|
||||
}
|
||||
|
||||
bool isActive() const {
|
||||
return active;
|
||||
}
|
||||
|
||||
void setPeerId(const char* peerId) {
|
||||
|
@ -193,5 +200,6 @@ public:
|
|||
};
|
||||
|
||||
typedef SharedHandle<Peer> PeerHandle;
|
||||
typedef deque<PeerHandle> Peers;
|
||||
|
||||
#endif // _D_PEER_H_
|
||||
|
|
|
@ -41,23 +41,25 @@
|
|||
|
||||
PeerAbstractCommand::PeerAbstractCommand(int cuid, const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
const SocketHandle& s)
|
||||
:Command(cuid), e(e), socket(s), peer(peer),
|
||||
checkSocketIsReadable(false), checkSocketIsWritable(false),
|
||||
uploadLimitCheck(false), uploadLimit(0), noCheck(false) {
|
||||
:BtContextAwareCommand(cuid, btContext), e(e), socket(s), peer(peer),
|
||||
checkSocketIsReadable(false), checkSocketIsWritable(false),
|
||||
uploadLimitCheck(false), uploadLimit(0), noCheck(false)
|
||||
{
|
||||
setReadCheckSocket(socket);
|
||||
timeout = e->option->getAsInt(PREF_TIMEOUT);
|
||||
e->torrentMan->connections++;
|
||||
btRuntime->increaseConnections();
|
||||
}
|
||||
|
||||
PeerAbstractCommand::~PeerAbstractCommand() {
|
||||
disableReadCheckSocket();
|
||||
disableWriteCheckSocket();
|
||||
e->torrentMan->connections--;
|
||||
btRuntime->decreaseConnections();
|
||||
}
|
||||
|
||||
bool PeerAbstractCommand::execute() {
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
#ifndef _D_PEER_ABSTRACT_COMMAND_H_
|
||||
#define _D_PEER_ABSTRACT_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "Request.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
|
||||
class PeerAbstractCommand : public Command {
|
||||
class PeerAbstractCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
Time checkPoint;
|
||||
int timeout;
|
||||
|
@ -48,6 +48,7 @@ protected:
|
|||
TorrentDownloadEngine* e;
|
||||
SocketHandle socket;
|
||||
PeerHandle peer;
|
||||
|
||||
void setTimeout(int timeout) { this->timeout = timeout; }
|
||||
virtual bool prepareForNextPeer(int wait);
|
||||
virtual bool prepareForRetry(int wait);
|
||||
|
@ -71,6 +72,7 @@ private:
|
|||
public:
|
||||
PeerAbstractCommand(int cuid, const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
const SocketHandle& s = SocketHandle());
|
||||
virtual ~PeerAbstractCommand();
|
||||
bool execute();
|
||||
|
|
|
@ -35,7 +35,14 @@
|
|||
#include "PeerChokeCommand.h"
|
||||
#include "Util.h"
|
||||
|
||||
PeerChokeCommand::PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), interval(interval), e(e), rotate(0) {}
|
||||
PeerChokeCommand::PeerChokeCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval):
|
||||
BtContextAwareCommand(cuid, btContext),
|
||||
interval(interval),
|
||||
e(e),
|
||||
rotate(0) {}
|
||||
|
||||
PeerChokeCommand::~PeerChokeCommand() {}
|
||||
|
||||
|
@ -89,14 +96,14 @@ void PeerChokeCommand::orderByDownloadRate(Peers& peers) const {
|
|||
}
|
||||
|
||||
bool PeerChokeCommand::execute() {
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
if(checkPoint.elapsed(interval)) {
|
||||
checkPoint.reset();
|
||||
Peers peers = e->torrentMan->getActivePeers();
|
||||
Peers peers = peerStorage->getActivePeers();
|
||||
for_each(peers.begin(), peers.end(), ChokePeer());
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
orderByUploadRate(peers);
|
||||
} else {
|
||||
orderByDownloadRate(peers);
|
||||
|
@ -109,7 +116,7 @@ bool PeerChokeCommand::execute() {
|
|||
peer->chokingRequired = false;
|
||||
peer->optUnchoking = false;
|
||||
itr = peers.erase(itr);
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
logger->debug("cat01, unchoking %s, upload speed=%d",
|
||||
peer->ipaddr.c_str(),
|
||||
peer->calculateUploadSpeed());
|
||||
|
@ -128,7 +135,7 @@ bool PeerChokeCommand::execute() {
|
|||
peer->chokingRequired = false;
|
||||
peer->optUnchoking = false;
|
||||
itr = peers.erase(itr);
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
logger->debug("cat01, unchoking %s, upload speed=%d",
|
||||
peer->ipaddr.c_str(),
|
||||
peer->calculateUploadSpeed());
|
||||
|
|
|
@ -35,11 +35,11 @@
|
|||
#ifndef _D_PEER_CHOKE_COMMAND_H_
|
||||
#define _D_PEER_CHOKE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
|
||||
class PeerChokeCommand : public Command {
|
||||
class PeerChokeCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
int interval;
|
||||
TorrentDownloadEngine* e;
|
||||
|
@ -51,7 +51,11 @@ private:
|
|||
void optUnchokingPeer(Peers& peers) const;
|
||||
|
||||
public:
|
||||
PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval);
|
||||
PeerChokeCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval);
|
||||
|
||||
virtual ~PeerChokeCommand();
|
||||
|
||||
bool execute();
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "Option.h"
|
||||
#include "Socket.h"
|
||||
#include "Logger.h"
|
||||
#include "TorrentMan.h"
|
||||
#include "PeerMessage.h"
|
||||
#include "common.h"
|
||||
|
||||
|
|
|
@ -41,8 +41,9 @@
|
|||
|
||||
PeerInitiateConnectionCommand::PeerInitiateConnectionCommand(int cuid,
|
||||
const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e)
|
||||
:PeerAbstractCommand(cuid, peer, e) {}
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext)
|
||||
:PeerAbstractCommand(cuid, peer, e, btContext) {}
|
||||
|
||||
PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand() {}
|
||||
|
||||
|
@ -51,7 +52,13 @@ bool PeerInitiateConnectionCommand::executeInternal() {
|
|||
logger->info(MSG_CONNECTING_TO_SERVER, cuid, peer->ipaddr.c_str(),
|
||||
peer->port);
|
||||
socket->establishConnection(peer->ipaddr, peer->port);
|
||||
command = new PeerInteractionCommand(cuid, peer, e, socket, PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE);
|
||||
command =
|
||||
new PeerInteractionCommand(cuid,
|
||||
peer,
|
||||
e,
|
||||
btContext,
|
||||
socket,
|
||||
PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE);
|
||||
|
||||
e->commands.push_back(command);
|
||||
return true;
|
||||
|
@ -59,19 +66,26 @@ bool PeerInitiateConnectionCommand::executeInternal() {
|
|||
|
||||
// TODO this method removed when PeerBalancerCommand is implemented
|
||||
bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) {
|
||||
if(e->torrentMan->isPeerAvailable()) {
|
||||
PeerHandle peer = e->torrentMan->getPeer();
|
||||
int newCuid = e->torrentMan->getNewCuid();
|
||||
if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) {
|
||||
PeerHandle peer = peerStorage->getUnusedPeer();
|
||||
int newCuid = btRuntime->getNewCuid();
|
||||
peer->cuid = newCuid;
|
||||
PeerInitiateConnectionCommand* command =
|
||||
new PeerInitiateConnectionCommand(newCuid, peer, e);
|
||||
new PeerInitiateConnectionCommand(newCuid,
|
||||
peer,
|
||||
e,
|
||||
btContext);
|
||||
e->commands.push_back(command);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PeerInitiateConnectionCommand::prepareForRetry(int wait) {
|
||||
PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(cuid, peer, e);
|
||||
PeerInitiateConnectionCommand* command =
|
||||
new PeerInitiateConnectionCommand(cuid,
|
||||
peer,
|
||||
e,
|
||||
btContext);
|
||||
e->commands.push_back(command);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -43,8 +43,11 @@ protected:
|
|||
bool prepareForRetry(int wait);
|
||||
bool prepareForNextPeer(int wait);
|
||||
public:
|
||||
PeerInitiateConnectionCommand(int cuid, const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e);
|
||||
PeerInitiateConnectionCommand(int cuid,
|
||||
const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext);
|
||||
|
||||
~PeerInitiateConnectionCommand();
|
||||
};
|
||||
|
||||
|
|
|
@ -39,20 +39,24 @@
|
|||
#include "PeerMessageUtil.h"
|
||||
#include "Util.h"
|
||||
#include "prefs.h"
|
||||
#include "BtRegistry.h"
|
||||
#include <netinet/in.h>
|
||||
|
||||
PeerInteraction::PeerInteraction(int cuid,
|
||||
const PeerHandle& peer,
|
||||
const SocketHandle& socket,
|
||||
const Option* op,
|
||||
TorrentMan* torrentMan)
|
||||
const BtContextHandle& btContext)
|
||||
:cuid(cuid),
|
||||
option(op),
|
||||
torrentMan(torrentMan),
|
||||
btContext(btContext),
|
||||
peerStorage(PEER_STORAGE(btContext)),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
btAnnounce(BT_ANNOUNCE(btContext)),
|
||||
peer(peer),
|
||||
quickReplied(false) {
|
||||
peerConnection = new PeerConnection(cuid, socket, op);
|
||||
peerMessageFactory = new PeerMessageFactory(cuid, this, peer);
|
||||
peerMessageFactory = new PeerMessageFactory(cuid, btContext, this, peer);
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
|
@ -78,7 +82,7 @@ void PeerInteraction::sendMessages() {
|
|||
PeerMessageHandle msg = messageQueue.front();
|
||||
messageQueue.pop_front();
|
||||
if(uploadLimit > 0) {
|
||||
TransferStat stat = torrentMan->calculateStat();
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
if(uploadLimit < stat.uploadSpeed &&
|
||||
msg->isUploading() && !msg->isInProgress()) {
|
||||
tempQueue.push_back(msg);
|
||||
|
@ -155,7 +159,7 @@ void PeerInteraction::abortPiece(Piece& piece) {
|
|||
itr++;
|
||||
}
|
||||
}
|
||||
torrentMan->cancelPiece(piece);
|
||||
pieceStorage->cancelPiece(piece);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +188,7 @@ void PeerInteraction::checkRequestSlot() {
|
|||
} else {
|
||||
Piece piece = getDownloadPiece(slot.getIndex());
|
||||
if(piece.hasBlock(slot.getBlockIndex()) ||
|
||||
torrentMan->hasPiece(piece.getIndex())) {
|
||||
pieceStorage->hasPiece(piece.getIndex())) {
|
||||
logger->debug("CUID#%d - Deleting request slot blockIndex=%d because"
|
||||
" the block has been acquired.", cuid,
|
||||
slot.getBlockIndex());
|
||||
|
@ -242,7 +246,7 @@ PeerMessageHandle PeerInteraction::receiveHandshake(bool quickReply) {
|
|||
if(!quickReplied && quickReply && msgLength >= 48) {
|
||||
quickReplied = true;
|
||||
// check info_hash
|
||||
if(memcmp(torrentMan->getInfoHash(), &msg[28], INFO_HASH_LENGTH) == 0) {
|
||||
if(memcmp(btContext->getInfoHash(), &msg[28], INFO_HASH_LENGTH) == 0) {
|
||||
sendHandshake();
|
||||
}
|
||||
}
|
||||
|
@ -272,18 +276,18 @@ PeerMessageHandle PeerInteraction::receiveMessage() {
|
|||
|
||||
void PeerInteraction::syncPiece() {
|
||||
for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
|
||||
torrentMan->syncPiece(*itr);
|
||||
pieceStorage->syncPiece(*itr);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerInteraction::updatePiece() {
|
||||
for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
|
||||
torrentMan->updatePiece(*itr);
|
||||
pieceStorage->updatePiece(*itr);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
|
||||
if(pieces.empty() && !torrentMan->hasMissingPiece(peer)) {
|
||||
if(pieces.empty() && !pieceStorage->hasMissingPiece(peer)) {
|
||||
if(peer->amInterested) {
|
||||
logger->debug("CUID#%d - Not interested in the peer", cuid);
|
||||
addMessage(peerMessageFactory->createNotInterestedMessage());
|
||||
|
@ -293,7 +297,7 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
|
|||
onChoked();
|
||||
if(peer->isFastExtensionEnabled()) {
|
||||
while((int)pieces.size() < pieceNum) {
|
||||
Piece piece = torrentMan->getMissingFastPiece(peer);
|
||||
Piece piece = pieceStorage->getMissingFastPiece(peer);
|
||||
if(Piece::isNull(piece)) {
|
||||
break;
|
||||
} else {
|
||||
|
@ -303,7 +307,7 @@ void PeerInteraction::getNewPieceAndSendInterest(int pieceNum) {
|
|||
}
|
||||
} else {
|
||||
while((int)pieces.size() < pieceNum) {
|
||||
Piece piece = torrentMan->getMissingPiece(peer);
|
||||
Piece piece = pieceStorage->getMissingPiece(peer);
|
||||
if(Piece::isNull(piece)) {
|
||||
break;
|
||||
} else {
|
||||
|
@ -338,16 +342,16 @@ void PeerInteraction::addRequests() {
|
|||
MAX_PENDING_REQUEST = 6;
|
||||
}
|
||||
int pieceNum;
|
||||
if(torrentMan->isEndGame()) {
|
||||
if(pieceStorage->isEndGame()) {
|
||||
pieceNum = 1;
|
||||
} else {
|
||||
int blocks = DIV_FLOOR(torrentMan->pieceLength, BLOCK_LENGTH);
|
||||
int blocks = DIV_FLOOR(btContext->getPieceLength(), BLOCK_LENGTH);
|
||||
pieceNum = DIV_FLOOR(MAX_PENDING_REQUEST, blocks);
|
||||
}
|
||||
getNewPieceAndSendInterest(pieceNum);
|
||||
for(Pieces::iterator itr = pieces.begin(); itr != pieces.end(); itr++) {
|
||||
Piece& piece = *itr;
|
||||
if(torrentMan->isEndGame()) {
|
||||
if(pieceStorage->isEndGame()) {
|
||||
BlockIndexes missingBlockIndexes = piece.getAllMissingBlockIndexes();
|
||||
random_shuffle(missingBlockIndexes.begin(), missingBlockIndexes.end());
|
||||
int count = countRequestSlot();
|
||||
|
@ -380,23 +384,23 @@ void PeerInteraction::addRequests() {
|
|||
|
||||
void PeerInteraction::sendHandshake() {
|
||||
PeerMessageHandle handle =
|
||||
peerMessageFactory->createHandshakeMessage(torrentMan->getInfoHash(),
|
||||
torrentMan->peerId.c_str());
|
||||
peerMessageFactory->createHandshakeMessage(btContext->getInfoHash(),
|
||||
btAnnounce->getPeerId().c_str());
|
||||
addMessage(handle);
|
||||
sendMessages();
|
||||
}
|
||||
|
||||
void PeerInteraction::sendBitfield() {
|
||||
if(peer->isFastExtensionEnabled()) {
|
||||
if(torrentMan->hasAllPieces()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
addMessage(peerMessageFactory->createHaveAllMessage());
|
||||
} else if(torrentMan->getDownloadLength() > 0) {
|
||||
} else if(pieceStorage->getCompletedLength() > 0) {
|
||||
addMessage(peerMessageFactory->createBitfieldMessage());
|
||||
} else {
|
||||
addMessage(peerMessageFactory->createHaveNoneMessage());
|
||||
}
|
||||
} else {
|
||||
if(torrentMan->getDownloadLength() > 0) {
|
||||
if(pieceStorage->getCompletedLength() > 0) {
|
||||
addMessage(peerMessageFactory->createBitfieldMessage());
|
||||
}
|
||||
}
|
||||
|
@ -405,8 +409,10 @@ void PeerInteraction::sendBitfield() {
|
|||
|
||||
void PeerInteraction::sendAllowedFast() {
|
||||
if(peer->isFastExtensionEnabled()) {
|
||||
Integers fastSet = Util::computeFastSet(peer->ipaddr, torrentMan->getInfoHash(),
|
||||
torrentMan->pieces, ALLOWED_FAST_SET_SIZE);
|
||||
Integers fastSet = Util::computeFastSet(peer->ipaddr,
|
||||
btContext->getInfoHash(),
|
||||
btContext->getNumPieces(),
|
||||
ALLOWED_FAST_SET_SIZE);
|
||||
for(Integers::const_iterator itr = fastSet.begin();
|
||||
itr != fastSet.end(); itr++) {
|
||||
addMessage(peerMessageFactory->createAllowedFastMessage(*itr));
|
||||
|
|
|
@ -37,9 +37,13 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "PeerConnection.h"
|
||||
#include "PeerMessageFactory.h"
|
||||
#include "RequestSlot.h"
|
||||
#include "SharedHandle.h"
|
||||
#include "PeerMessageFactory.h"
|
||||
#include "BtContext.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtAnnounce.h"
|
||||
|
||||
#define REQUEST_TIME_OUT 60
|
||||
#define ALLOWED_FAST_SET_SIZE 10
|
||||
|
@ -53,7 +57,10 @@ private:
|
|||
RequestSlots requestSlots;
|
||||
MessageQueue messageQueue;
|
||||
const Option* option;
|
||||
TorrentMan* torrentMan;
|
||||
BtContextHandle btContext;
|
||||
PeerStorageHandle peerStorage;
|
||||
PieceStorageHandle pieceStorage;
|
||||
BtAnnounceHandle btAnnounce;
|
||||
PeerConnection* peerConnection;
|
||||
PeerHandle peer;
|
||||
Pieces pieces;
|
||||
|
@ -70,7 +77,7 @@ public:
|
|||
const PeerHandle& peer,
|
||||
const SocketHandle& socket,
|
||||
const Option* op,
|
||||
TorrentMan* torrentMan);
|
||||
const BtContextHandle& btContext);
|
||||
~PeerInteraction();
|
||||
|
||||
void addMessage(const PeerMessageHandle& peerMessage);
|
||||
|
@ -89,16 +96,20 @@ public:
|
|||
|
||||
int countMessageInQueue() const;
|
||||
|
||||
TorrentMan* getTorrentMan() const { return torrentMan; }
|
||||
BtContextHandle getBtContext() const { return btContext; }
|
||||
|
||||
PeerConnection* getPeerConnection() const { return peerConnection; }
|
||||
|
||||
// If this object has nullPiece, then return false, otherwise true
|
||||
bool hasDownloadPiece(int index) const;
|
||||
|
||||
// If the piece which this object has is nullPiece, then throws an exception.
|
||||
// So before calling this function, call hasDownloadPiece and make sure
|
||||
// this has valid piece, not nullPiece.
|
||||
Piece& getDownloadPiece(int index);
|
||||
|
||||
bool isInFastSet(int index) const;
|
||||
|
||||
void addFastSetIndex(int index);
|
||||
|
||||
void syncPiece();
|
||||
|
|
|
@ -49,26 +49,27 @@
|
|||
PeerInteractionCommand::PeerInteractionCommand(int cuid,
|
||||
const PeerHandle& p,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
const SocketHandle& s,
|
||||
int sequence)
|
||||
:PeerAbstractCommand(cuid, p, e, s), sequence(sequence) {
|
||||
:PeerAbstractCommand(cuid, p, e, btContext, s), sequence(sequence) {
|
||||
if(sequence == INITIATOR_SEND_HANDSHAKE) {
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(socket);
|
||||
setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
|
||||
}
|
||||
peerInteraction = new PeerInteraction(cuid, peer, socket, e->option,
|
||||
e->torrentMan);
|
||||
btContext);
|
||||
setUploadLimit(e->option->getAsInt(PREF_MAX_UPLOAD_LIMIT));
|
||||
chokeUnchokeCount = 0;
|
||||
haveCount = 0;
|
||||
keepAliveCount = 0;
|
||||
e->torrentMan->addActivePeer(peer);
|
||||
peer->activate();
|
||||
}
|
||||
|
||||
PeerInteractionCommand::~PeerInteractionCommand() {
|
||||
delete peerInteraction;
|
||||
e->torrentMan->deleteActivePeer(peer);
|
||||
peer->deactivate();
|
||||
}
|
||||
|
||||
bool PeerInteractionCommand::executeInternal() {
|
||||
|
@ -173,7 +174,7 @@ void PeerInteractionCommand::detectMessageFlooding() {
|
|||
|
||||
/*
|
||||
void PeerInteractionCommand::checkLongTimePeerChoking() {
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
return;
|
||||
}
|
||||
if(peer->amInterested && peer->peerChoking) {
|
||||
|
@ -205,7 +206,7 @@ void PeerInteractionCommand::receiveMessages() {
|
|||
for(int i = 0; i < 50; i++) {
|
||||
int maxSpeedLimit = e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT);
|
||||
if(maxSpeedLimit > 0) {
|
||||
TransferStat stat = e->torrentMan->calculateStat();
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
if(maxSpeedLimit < stat.downloadSpeed) {
|
||||
disableReadCheckSocket();
|
||||
setNoCheck(true);
|
||||
|
@ -245,12 +246,15 @@ void PeerInteractionCommand::receiveMessages() {
|
|||
|
||||
// TODO this method removed when PeerBalancerCommand is implemented
|
||||
bool PeerInteractionCommand::prepareForNextPeer(int wait) {
|
||||
if(e->torrentMan->isPeerAvailable()) {
|
||||
PeerHandle peer = e->torrentMan->getPeer();
|
||||
int newCuid = e->torrentMan->getNewCuid();
|
||||
if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) {
|
||||
PeerHandle peer = peerStorage->getUnusedPeer();
|
||||
int newCuid = btRuntime->getNewCuid();
|
||||
peer->cuid = newCuid;
|
||||
PeerInitiateConnectionCommand* command =
|
||||
new PeerInitiateConnectionCommand(newCuid, peer, e);
|
||||
new PeerInitiateConnectionCommand(newCuid,
|
||||
peer,
|
||||
e,
|
||||
btContext);
|
||||
e->commands.push_back(command);
|
||||
}
|
||||
return true;
|
||||
|
@ -278,12 +282,12 @@ void PeerInteractionCommand::sendKeepAlive() {
|
|||
}
|
||||
|
||||
void PeerInteractionCommand::checkHave() {
|
||||
PieceIndexes indexes =
|
||||
e->torrentMan->getAdvertisedPieceIndexes(cuid, haveCheckTime);
|
||||
Integers indexes =
|
||||
pieceStorage->getAdvertisedPieceIndexes(cuid, haveCheckTime);
|
||||
haveCheckTime.reset();
|
||||
if(indexes.size() >= 20) {
|
||||
if(peer->isFastExtensionEnabled()) {
|
||||
if(e->torrentMan->hasAllPieces()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
|
||||
createHaveAllMessage());
|
||||
} else {
|
||||
|
@ -295,7 +299,7 @@ void PeerInteractionCommand::checkHave() {
|
|||
createBitfieldMessage());
|
||||
}
|
||||
} else {
|
||||
for(PieceIndexes::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
||||
for(Integers::iterator itr = indexes.begin(); itr != indexes.end(); itr++) {
|
||||
peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
|
||||
createHaveMessage(*itr));
|
||||
}
|
||||
|
|
|
@ -73,7 +73,9 @@ protected:
|
|||
public:
|
||||
PeerInteractionCommand(int cuid, const PeerHandle& peer,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
const SocketHandle& s, int sequence);
|
||||
|
||||
~PeerInteractionCommand();
|
||||
|
||||
enum Seq {
|
||||
|
|
|
@ -40,8 +40,6 @@
|
|||
#include "Peer.h"
|
||||
#include "SharedHandle.h"
|
||||
|
||||
typedef deque<PeerHandle> Peers;
|
||||
|
||||
class PeerListProcessor {
|
||||
public:
|
||||
virtual ~PeerListProcessor() {}
|
||||
|
|
|
@ -35,8 +35,11 @@
|
|||
#include "PeerListenCommand.h"
|
||||
#include "PeerInteractionCommand.h"
|
||||
|
||||
PeerListenCommand::PeerListenCommand(int cuid, TorrentDownloadEngine* e)
|
||||
:Command(cuid), e(e) {}
|
||||
PeerListenCommand::PeerListenCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext)
|
||||
:BtContextAwareCommand(cuid, btContext),
|
||||
e(e) {}
|
||||
|
||||
PeerListenCommand::~PeerListenCommand() {}
|
||||
|
||||
|
@ -61,7 +64,7 @@ int PeerListenCommand::bindPort(int portRangeStart, int portRangeEnd) {
|
|||
}
|
||||
|
||||
bool PeerListenCommand::execute() {
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
for(int i = 0; i < 3 && socket->isReadable(0); i++) {
|
||||
|
@ -73,15 +76,17 @@ bool PeerListenCommand::execute() {
|
|||
pair<string, int> localInfo;
|
||||
peerSocket->getAddrInfo(localInfo);
|
||||
if(peerInfo.first != localInfo.first &&
|
||||
e->torrentMan->connections < MAX_PEERS) {
|
||||
btRuntime->getConnections() < MAX_PEERS) {
|
||||
PeerHandle peer = PeerHandle(new Peer(peerInfo.first, peerInfo.second,
|
||||
e->torrentMan->pieceLength,
|
||||
e->torrentMan->getTotalLength()));
|
||||
if(e->torrentMan->addPeer(peer)) {
|
||||
int newCuid = e->torrentMan->getNewCuid();
|
||||
btContext->getPieceLength(),
|
||||
btContext->getTotalLength()));
|
||||
if(peerStorage->addPeer(peer)) {
|
||||
int newCuid = btRuntime->getNewCuid();
|
||||
peer->cuid = newCuid;
|
||||
PeerInteractionCommand* command =
|
||||
new PeerInteractionCommand(newCuid, peer, e, peerSocket,
|
||||
new PeerInteractionCommand(newCuid, peer, e,
|
||||
btContext,
|
||||
peerSocket,
|
||||
PeerInteractionCommand::RECEIVER_WAIT_HANDSHAKE);
|
||||
e->commands.push_back(command);
|
||||
logger->debug("CUID#%d - incoming connection, adding new command CUID#%d", cuid, newCuid);
|
||||
|
|
|
@ -35,15 +35,18 @@
|
|||
#ifndef _D_PEER_LISTEN_COMMAND_H_
|
||||
#define _D_PEER_LISTEN_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
|
||||
class PeerListenCommand : public Command {
|
||||
class PeerListenCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
SocketHandle socket;
|
||||
public:
|
||||
PeerListenCommand(int cuid, TorrentDownloadEngine* e);
|
||||
PeerListenCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext);
|
||||
|
||||
~PeerListenCommand();
|
||||
|
||||
bool execute();
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
PeerMessage::PeerMessage()
|
||||
:inProgress(false),
|
||||
invalidate(false),
|
||||
uploading(false) {
|
||||
uploading(false),
|
||||
btContext(0),
|
||||
peerStorage(0),
|
||||
pieceStorage(0)
|
||||
{
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
|
|
@ -39,7 +39,10 @@
|
|||
#include "Logger.h"
|
||||
#include "Peer.h"
|
||||
#include "Piece.h"
|
||||
#include "SharedHandle.h"
|
||||
#include "BtContext.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtRegistry.h"
|
||||
#include <string>
|
||||
|
||||
class PeerInteraction;
|
||||
|
@ -53,6 +56,9 @@ protected:
|
|||
PeerHandle peer;
|
||||
PeerInteraction* peerInteraction;
|
||||
const Logger* logger;
|
||||
BtContextHandle btContext;
|
||||
PeerStorageHandle peerStorage;
|
||||
PieceStorageHandle pieceStorage;
|
||||
public:
|
||||
PeerMessage();
|
||||
|
||||
|
@ -63,18 +69,29 @@ public:
|
|||
bool isUploading() const { return uploading; }
|
||||
|
||||
int getCuid() const { return cuid; }
|
||||
|
||||
void setCuid(int cuid) {
|
||||
this->cuid = cuid;
|
||||
}
|
||||
|
||||
PeerHandle getPeer() const { return this->peer; }
|
||||
|
||||
void setPeer(const PeerHandle& peer) {
|
||||
this->peer = peer;
|
||||
}
|
||||
|
||||
PeerInteraction* getPeerInteraction() const { return peerInteraction; }
|
||||
|
||||
void setPeerInteraction(PeerInteraction* peerInteraction) {
|
||||
this->peerInteraction = peerInteraction;
|
||||
}
|
||||
|
||||
void setBtContext(const BtContextHandle& btContext) {
|
||||
this->btContext = btContext;
|
||||
pieceStorage = PIECE_STORAGE(btContext);
|
||||
peerStorage = PEER_STORAGE(btContext);
|
||||
}
|
||||
|
||||
virtual int getId() const = 0;
|
||||
virtual void receivedAction() = 0;
|
||||
virtual void send() = 0;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
*/
|
||||
/* copyright --> */
|
||||
#include "PeerMessageFactory.h"
|
||||
#include "PeerInteraction.h"
|
||||
#include "PeerMessageUtil.h"
|
||||
#include "ChokeMessage.h"
|
||||
#include "UnchokeMessage.h"
|
||||
|
@ -54,11 +53,16 @@
|
|||
#include "SuggestPieceMessage.h"
|
||||
#include "RequestSlot.h"
|
||||
#include "DlAbortEx.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "PeerInteraction.h"
|
||||
|
||||
PeerMessageFactory::PeerMessageFactory(int cuid,
|
||||
const BtContextHandle& btContext,
|
||||
PeerInteraction* peerInteraction,
|
||||
const PeerHandle& peer)
|
||||
:cuid(cuid),
|
||||
btContext(btContext),
|
||||
pieceStorage(PIECE_STORAGE(btContext)),
|
||||
peerInteraction(peerInteraction),
|
||||
peer(peer) {}
|
||||
|
||||
|
@ -86,29 +90,26 @@ PeerMessageHandle PeerMessageFactory::createPeerMessage(const char* msg, int msg
|
|||
break;
|
||||
case HaveMessage::ID:
|
||||
peerMessage = HaveMessage::create(msg, msgLength);
|
||||
((HaveMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->
|
||||
pieces);
|
||||
((HaveMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
break;
|
||||
case BitfieldMessage::ID:
|
||||
peerMessage = BitfieldMessage::create(msg, msgLength);
|
||||
((BitfieldMessage*)peerMessage)->setPieces(peerInteraction->
|
||||
getTorrentMan()->pieces);
|
||||
((BitfieldMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
break;
|
||||
case RequestMessage::ID:
|
||||
peerMessage = RequestMessage::create(msg, msgLength);
|
||||
((RequestMessage*)peerMessage)->setPieces(peerInteraction->
|
||||
getTorrentMan()->pieces);
|
||||
((RequestMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((RequestMessage*)peerMessage)->getIndex()));
|
||||
((RequestMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
((RequestMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((RequestMessage*)peerMessage)->getIndex()));
|
||||
break;
|
||||
case CancelMessage::ID:
|
||||
peerMessage = CancelMessage::create(msg, msgLength);
|
||||
((CancelMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces);
|
||||
((CancelMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((CancelMessage*)peerMessage)->getIndex()));
|
||||
((CancelMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
((CancelMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((CancelMessage*)peerMessage)->getIndex()));
|
||||
break;
|
||||
case PieceMessage::ID:
|
||||
peerMessage = PieceMessage::create(msg, msgLength);
|
||||
((PieceMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces);
|
||||
((PieceMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((PieceMessage*)peerMessage)->getIndex()));
|
||||
((PieceMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
((PieceMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((PieceMessage*)peerMessage)->getIndex()));
|
||||
break;
|
||||
case PortMessage::ID:
|
||||
peerMessage = PortMessage::create(msg, msgLength);
|
||||
|
@ -121,16 +122,16 @@ PeerMessageHandle PeerMessageFactory::createPeerMessage(const char* msg, int msg
|
|||
break;
|
||||
case RejectMessage::ID:
|
||||
peerMessage = RejectMessage::create(msg, msgLength);
|
||||
((RejectMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces);
|
||||
((RejectMessage*)peerMessage)->setPieceLength(peerInteraction->getTorrentMan()->getPieceLength(((RejectMessage*)peerMessage)->getIndex()));
|
||||
((RejectMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
((RejectMessage*)peerMessage)->setPieceLength(pieceStorage->getPieceLength(((RejectMessage*)peerMessage)->getIndex()));
|
||||
break;
|
||||
case SuggestPieceMessage::ID:
|
||||
peerMessage = SuggestPieceMessage::create(msg, msgLength);
|
||||
((SuggestPieceMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces);
|
||||
((SuggestPieceMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
break;
|
||||
case AllowedFastMessage::ID:
|
||||
peerMessage = AllowedFastMessage::create(msg, msgLength);
|
||||
((AllowedFastMessage*)peerMessage)->setPieces(peerInteraction->getTorrentMan()->pieces);
|
||||
((AllowedFastMessage*)peerMessage)->setPieces(btContext->getNumPieces());
|
||||
break;
|
||||
default:
|
||||
throw new DlAbortEx("Invalid message id. id = %d", id);
|
||||
|
@ -167,6 +168,7 @@ PeerMessageFactory::setPeerMessageCommonProperty(PeerMessageHandle& peerMessage)
|
|||
peerMessage->setPeer(peer);
|
||||
peerMessage->setCuid(cuid);
|
||||
peerMessage->setPeerInteraction(peerInteraction);
|
||||
peerMessage->setBtContext(btContext);
|
||||
}
|
||||
|
||||
PeerMessageHandle PeerMessageFactory::createRequestMessage(const Piece& piece,
|
||||
|
@ -235,10 +237,8 @@ PeerMessageHandle PeerMessageFactory::createNotInterestedMessage() const {
|
|||
|
||||
PeerMessageHandle PeerMessageFactory::createBitfieldMessage() const {
|
||||
PeerMessageHandle handle =
|
||||
PeerMessageHandle(new BitfieldMessage(peerInteraction->getTorrentMan()->
|
||||
getBitfield(),
|
||||
peerInteraction->getTorrentMan()->
|
||||
getBitfieldLength()));
|
||||
PeerMessageHandle(new BitfieldMessage(pieceStorage->getBitfield(),
|
||||
pieceStorage->getBitfieldLength()));
|
||||
setPeerMessageCommonProperty(handle);
|
||||
return handle;
|
||||
}
|
||||
|
|
|
@ -38,18 +38,23 @@
|
|||
#include "common.h"
|
||||
#include "PeerMessage.h"
|
||||
#include "HandshakeMessage.h"
|
||||
#include "BtContext.h"
|
||||
#include "PieceStorage.h"
|
||||
|
||||
class PeerInteraction;
|
||||
|
||||
class PeerMessageFactory {
|
||||
private:
|
||||
int cuid;
|
||||
BtContextHandle btContext;
|
||||
PieceStorageHandle pieceStorage;
|
||||
PeerInteraction* peerInteraction;
|
||||
PeerHandle peer;
|
||||
|
||||
void setPeerMessageCommonProperty(PeerMessageHandle& peerMessage) const;
|
||||
public:
|
||||
PeerMessageFactory(int cuid,
|
||||
const BtContextHandle& btContext,
|
||||
PeerInteraction* peerInteraction,
|
||||
const PeerHandle& peer);
|
||||
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_PEER_STORAGE_H_
|
||||
#define _D_PEER_STORAGE_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "Peer.h"
|
||||
|
||||
class TransferStat {
|
||||
public:
|
||||
int downloadSpeed;
|
||||
int uploadSpeed;
|
||||
long long int sessionDownloadLength;
|
||||
long long int sessionUploadLength;
|
||||
public:
|
||||
TransferStat():downloadSpeed(0), uploadSpeed(0),
|
||||
sessionDownloadLength(0), sessionUploadLength(0) {}
|
||||
|
||||
int getDownloadSpeed() const {
|
||||
return downloadSpeed;
|
||||
}
|
||||
|
||||
void setDownloadSpeed(int s) { downloadSpeed = s; }
|
||||
|
||||
int getUploadSpeed() const {
|
||||
return uploadSpeed;
|
||||
}
|
||||
|
||||
void setUploadSpeed(int s) { uploadSpeed = s; }
|
||||
|
||||
/**
|
||||
* Returns the number of bytes downloaded since the program started.
|
||||
* This is not the total number of bytes downloaded.
|
||||
*/
|
||||
long long int getSessionDownloadLength() const {
|
||||
return sessionDownloadLength;
|
||||
}
|
||||
|
||||
void setSessionDownloadLength(long long int s) { sessionDownloadLength = s; }
|
||||
|
||||
/**
|
||||
* Returns the number of bytes uploaded since the program started.
|
||||
* This is not the total number of bytes uploaded.
|
||||
*/
|
||||
long long int getSessionUploadLength() const {
|
||||
return sessionUploadLength;
|
||||
}
|
||||
|
||||
void setSessionUploadLength(long long int s) { sessionUploadLength = s; }
|
||||
};
|
||||
|
||||
class PeerStorage {
|
||||
public:
|
||||
virtual ~PeerStorage() {}
|
||||
|
||||
/**
|
||||
* Adds new peer to internal peer list.
|
||||
* If the peer is added successfully, returns true. Otherwise returns false.
|
||||
*/
|
||||
virtual bool addPeer(const PeerHandle& peer) = 0;
|
||||
|
||||
/**
|
||||
* Adds all peers in peers to internal peer list.
|
||||
*/
|
||||
virtual void addPeer(const Peers& peers) = 0;
|
||||
|
||||
/**
|
||||
* Returns internal peer list.
|
||||
*/
|
||||
virtual const Peers& getPeers() = 0;
|
||||
|
||||
/**
|
||||
* Returns one of the unused peers.
|
||||
*/
|
||||
virtual PeerHandle getUnusedPeer() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if at least one unused peer exists.
|
||||
* Otherwise returns false.
|
||||
*/
|
||||
virtual bool isPeerAvailable() = 0;
|
||||
|
||||
/**
|
||||
* Returns the list of peers which are currently connected from localhost.
|
||||
*/
|
||||
virtual Peers getActivePeers() = 0;
|
||||
|
||||
/**
|
||||
* Calculates current download/upload statistics.
|
||||
*/
|
||||
virtual TransferStat calculateStat() = 0;
|
||||
};
|
||||
|
||||
typedef SharedHandle<PeerStorage> PeerStorageHandle;
|
||||
|
||||
#endif // _D_PEER_STORAGE_H_
|
|
@ -33,6 +33,7 @@
|
|||
*/
|
||||
/* copyright --> */
|
||||
#include "Piece.h"
|
||||
#include "Util.h"
|
||||
|
||||
Piece Piece::nullPiece;
|
||||
|
||||
|
@ -79,3 +80,7 @@ int Piece::getMissingBlockIndex() const {
|
|||
BlockIndexes Piece::getAllMissingBlockIndexes() const {
|
||||
return bitfield->getAllMissingIndexes();
|
||||
}
|
||||
|
||||
string Piece::toString() const {
|
||||
return "piece: index="+Util::itos(index)+", length="+Util::itos(length);
|
||||
}
|
||||
|
|
|
@ -117,10 +117,14 @@ public:
|
|||
void clearAllBlock();
|
||||
void setAllBlock();
|
||||
|
||||
string toString() const;
|
||||
|
||||
static Piece nullPiece;
|
||||
static bool isNull(const Piece& piece) {
|
||||
return piece.index == 0 && piece.length == 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef deque<Piece> Pieces;
|
||||
|
||||
#endif // _D_PIECE_H_
|
||||
|
|
|
@ -65,7 +65,6 @@ PieceMessage* PieceMessage::create(const char* data, int dataLength) {
|
|||
}
|
||||
|
||||
void PieceMessage::receivedAction() {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
RequestSlot slot = peerInteraction->getCorrespondingRequestSlot(index,
|
||||
begin,
|
||||
blockLength);
|
||||
|
@ -77,15 +76,15 @@ void PieceMessage::receivedAction() {
|
|||
peer->updateLatency(slot.getLatencyInMillis());
|
||||
Piece& piece = peerInteraction->getDownloadPiece(slot.getIndex());
|
||||
long long int offset =
|
||||
((long long int)index)*torrentMan->pieceLength+begin;
|
||||
((long long int)index)*btContext->getPieceLength()+begin;
|
||||
logger->debug("CUID#%d - Writing the block length=%d, offset=%lld",
|
||||
cuid, blockLength, offset);
|
||||
torrentMan->diskAdaptor->writeData(block,
|
||||
blockLength,
|
||||
offset);
|
||||
pieceStorage->getDiskAdaptor()->writeData(block,
|
||||
blockLength,
|
||||
offset);
|
||||
piece.completeBlock(slot.getBlockIndex());
|
||||
peerInteraction->deleteRequestSlot(slot);
|
||||
torrentMan->updatePiece(piece);
|
||||
pieceStorage->updatePiece(piece);
|
||||
logger->debug("CUID#%d - Setting piece block index=%d",
|
||||
cuid, slot.getBlockIndex());
|
||||
if(piece.pieceComplete()) {
|
||||
|
@ -123,7 +122,6 @@ void PieceMessage::send() {
|
|||
if(invalidate) {
|
||||
return;
|
||||
}
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
PeerConnection* peerConnection = peerInteraction->getPeerConnection();
|
||||
if(!headerSent) {
|
||||
if(!inProgress) {
|
||||
|
@ -146,13 +144,11 @@ void PieceMessage::send() {
|
|||
}
|
||||
if(headerSent) {
|
||||
inProgress = false;
|
||||
int pieceLength = torrentMan->pieceLength;
|
||||
long long int pieceDataOffset =
|
||||
((long long int)index)*pieceLength+begin+blockLength-leftDataLength;
|
||||
((long long int)index)*btContext->getPieceLength()+begin+blockLength-leftDataLength;
|
||||
int writtenLength =
|
||||
sendPieceData(pieceDataOffset, leftDataLength);
|
||||
peer->updateUploadLength(writtenLength);
|
||||
torrentMan->addUploadLength(writtenLength);
|
||||
if(writtenLength != leftDataLength) {
|
||||
inProgress = true;
|
||||
}
|
||||
|
@ -165,10 +161,9 @@ int PieceMessage::sendPieceData(long long int offset, int length) const {
|
|||
char buf[BUF_SIZE];
|
||||
int iteration = length/BUF_SIZE;
|
||||
int writtenLength = 0;
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
PeerConnection* peerConnection = peerInteraction->getPeerConnection();
|
||||
for(int i = 0; i < iteration; i++) {
|
||||
if(torrentMan->diskAdaptor->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
|
||||
if(pieceStorage->getDiskAdaptor()->readData(buf, BUF_SIZE, offset+i*BUF_SIZE) < BUF_SIZE) {
|
||||
throw new DlAbortEx("Failed to read data from disk.");
|
||||
}
|
||||
int ws = peerConnection->sendMessage(buf, BUF_SIZE);
|
||||
|
@ -181,7 +176,7 @@ int PieceMessage::sendPieceData(long long int offset, int length) const {
|
|||
|
||||
int rem = length%BUF_SIZE;
|
||||
if(rem > 0) {
|
||||
if(torrentMan->diskAdaptor->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
|
||||
if(pieceStorage->getDiskAdaptor()->readData(buf, rem, offset+iteration*BUF_SIZE) < rem) {
|
||||
throw new DlAbortEx("Failed to read data from disk.");
|
||||
}
|
||||
int ws = peerConnection->sendMessage(buf, rem);
|
||||
|
@ -202,42 +197,39 @@ string PieceMessage::toString() const {
|
|||
}
|
||||
|
||||
bool PieceMessage::checkPieceHash(const Piece& piece) {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
long long int offset =
|
||||
((long long int)piece.getIndex())*torrentMan->pieceLength;
|
||||
return torrentMan->diskAdaptor->sha1Sum(offset, piece.getLength()) ==
|
||||
torrentMan->getPieceHash(piece.getIndex());
|
||||
((long long int)piece.getIndex())*btContext->getPieceLength();
|
||||
return pieceStorage->getDiskAdaptor()->sha1Sum(offset, piece.getLength()) ==
|
||||
btContext->getPieceHash(piece.getIndex());
|
||||
}
|
||||
|
||||
void PieceMessage::onGotNewPiece(Piece& piece) {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
logger->info(MSG_GOT_NEW_PIECE, cuid, piece.getIndex());
|
||||
torrentMan->completePiece(piece);
|
||||
torrentMan->advertisePiece(cuid, piece.getIndex());
|
||||
pieceStorage->completePiece(piece);
|
||||
pieceStorage->advertisePiece(cuid, piece.getIndex());
|
||||
}
|
||||
|
||||
void PieceMessage::onGotWrongPiece(Piece& piece) {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
logger->error(MSG_GOT_WRONG_PIECE, cuid, piece.getIndex());
|
||||
erasePieceOnDisk(piece);
|
||||
piece.clearAllBlock();
|
||||
torrentMan->updatePiece(piece);
|
||||
pieceStorage->updatePiece(piece);
|
||||
peerInteraction->abortPiece(piece);
|
||||
}
|
||||
|
||||
void PieceMessage::erasePieceOnDisk(const Piece& piece) {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
int BUFSIZE = 4096;
|
||||
char buf[BUFSIZE];
|
||||
memset(buf, 0, BUFSIZE);
|
||||
long long int offset = ((long long int)piece.getIndex())*torrentMan->pieceLength;
|
||||
long long int offset =
|
||||
((long long int)piece.getIndex())*btContext->getPieceLength();
|
||||
for(int i = 0; i < piece.getLength()/BUFSIZE; i++) {
|
||||
torrentMan->diskAdaptor->writeData(buf, BUFSIZE, offset);
|
||||
pieceStorage->getDiskAdaptor()->writeData(buf, BUFSIZE, offset);
|
||||
offset += BUFSIZE;
|
||||
}
|
||||
int r = piece.getLength()%BUFSIZE;
|
||||
if(r > 0) {
|
||||
torrentMan->diskAdaptor->writeData(buf, r, offset);
|
||||
pieceStorage->getDiskAdaptor()->writeData(buf, r, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#define _D_PIECE_MESSAGE_H_
|
||||
|
||||
#include "PeerMessage.h"
|
||||
#include "TorrentMan.h"
|
||||
|
||||
class PieceMessage : public PeerMessage {
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2006 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef _D_PIECE_STORAGE_H_
|
||||
#define _D_PIECE_STORAGE_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "Peer.h"
|
||||
#include "Piece.h"
|
||||
#include "DiskAdaptor.h"
|
||||
|
||||
class PieceStorage {
|
||||
public:
|
||||
virtual ~PieceStorage() {}
|
||||
|
||||
/**
|
||||
* Returns true if the peer has a piece that localhost doesn't have.
|
||||
* Otherwise returns false.
|
||||
*/
|
||||
virtual bool hasMissingPiece(const PeerHandle& peer) = 0;
|
||||
|
||||
/**
|
||||
* Returns a piece that the peer has but localhost doesn't.
|
||||
* The piece will be marked "used" status in order to prevent other command
|
||||
* from get the same piece. But in end game mode, same piece may be returned
|
||||
* to several commands.
|
||||
*/
|
||||
virtual Piece getMissingPiece(const PeerHandle& peer) = 0;
|
||||
/**
|
||||
* Returns a piece that the peer has but localhost doesn't.
|
||||
* Only pieces that declared as "fast" are returned.
|
||||
* The piece will be marked "used" status in order to prevent other command
|
||||
* from get the same piece. But in end game mode, same piece may be returned
|
||||
* to several commands.
|
||||
*/
|
||||
virtual Piece getMissingFastPiece(const PeerHandle& peer) = 0;
|
||||
|
||||
/**
|
||||
* Tells that the download of the specfied piece completes.
|
||||
*/
|
||||
virtual void completePiece(const Piece& piece) = 0;
|
||||
|
||||
/**
|
||||
* Tells that the download of the specified piece is canceled.
|
||||
*/
|
||||
virtual void cancelPiece(const Piece& piece) = 0;
|
||||
|
||||
/**
|
||||
* Updates the internal piece data with the specified piece data.
|
||||
*/
|
||||
virtual void updatePiece(const Piece& piece) = 0;
|
||||
|
||||
/**
|
||||
* Updates the spcefied piece data with the internal piece data.
|
||||
*/
|
||||
virtual void syncPiece(Piece& piece) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the specified piece is already downloaded.
|
||||
* Otherwise returns false.
|
||||
*/
|
||||
virtual bool hasPiece(int index) = 0;
|
||||
|
||||
virtual long long int getTotalLength() = 0;
|
||||
|
||||
virtual long long int getFilteredTotalLength() = 0;
|
||||
|
||||
virtual long long int getCompletedLength() = 0;
|
||||
|
||||
virtual long long int getFilteredCompletedLength() = 0;
|
||||
|
||||
virtual void setFileFilter(const Strings& filePaths) = 0;
|
||||
|
||||
virtual void setFileFilter(const Integers& fileIndexes) = 0;
|
||||
|
||||
virtual void clearFileFilter() = 0;
|
||||
|
||||
virtual bool downloadFinished() = 0;
|
||||
|
||||
/**
|
||||
* Initializes DiskAdaptor.
|
||||
* TODO add better documentation here.
|
||||
*/
|
||||
virtual void initStorage() = 0;
|
||||
|
||||
virtual const unsigned char* getBitfield() = 0;
|
||||
|
||||
virtual void setBitfield(const unsigned char* bitfield,
|
||||
int bitfieldLength) = 0;
|
||||
|
||||
virtual int getBitfieldLength() = 0;
|
||||
|
||||
virtual bool isSelectiveDownloadingMode() = 0;
|
||||
|
||||
virtual void finishSelectiveDownloadingMode() = 0;
|
||||
|
||||
virtual bool isEndGame() = 0;
|
||||
|
||||
virtual DiskAdaptor* getDiskAdaptor() = 0;
|
||||
|
||||
virtual int getPieceLength(int index) = 0;
|
||||
|
||||
/**
|
||||
* Adds piece index to advertise to other commands. They send have message
|
||||
* based on this information.
|
||||
*/
|
||||
virtual void advertisePiece(int cuid, int index) = 0;
|
||||
|
||||
/**
|
||||
* Returns piece index which is not advertised by the caller command and
|
||||
* newer than lastCheckTime.
|
||||
*/
|
||||
virtual Integers getAdvertisedPieceIndexes(int myCuid,
|
||||
const Time& lastCheckTime) = 0;
|
||||
|
||||
/**
|
||||
* Removes have entry if specified seconds have elapsed since its
|
||||
* registration.
|
||||
*/
|
||||
virtual void removeAdvertisedPiece(int elapsed) = 0;
|
||||
|
||||
};
|
||||
|
||||
typedef SharedHandle<PieceStorage> PieceStorageHandle;
|
||||
|
||||
#endif // _D_PIECE_STORAGE_H_
|
|
@ -36,7 +36,6 @@
|
|||
#define _D_REJECT_MESSAGE_H_
|
||||
|
||||
#include "SimplePeerMessage.h"
|
||||
#include "TorrentMan.h"
|
||||
|
||||
class RejectMessage : public SimplePeerMessage {
|
||||
private:
|
||||
|
|
|
@ -55,8 +55,7 @@ RequestMessage* RequestMessage::create(const char* data, int dataLength) {
|
|||
}
|
||||
|
||||
void RequestMessage::receivedAction() {
|
||||
TorrentMan* torrentMan = peerInteraction->getTorrentMan();
|
||||
if(torrentMan->hasPiece(index) &&
|
||||
if(pieceStorage->hasPiece(index) &&
|
||||
(!peer->amChoking ||
|
||||
peer->amChoking && peerInteraction->isInFastSet(index))) {
|
||||
peerInteraction->addMessage(peerInteraction->getPeerMessageFactory()->
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#define _D_REQUEST_MESSAGE_H_
|
||||
|
||||
#include "SimplePeerMessage.h"
|
||||
#include "TorrentMan.h"
|
||||
|
||||
class RequestMessage : public SimplePeerMessage {
|
||||
private:
|
||||
|
|
|
@ -34,8 +34,17 @@
|
|||
/* copyright --> */
|
||||
#include "SeedCheckCommand.h"
|
||||
|
||||
SeedCheckCommand::SeedCheckCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
SeedCriteriaHandle seedCriteria)
|
||||
:BtContextAwareCommand(cuid, btContext),
|
||||
e(e),
|
||||
seedCriteria(seedCriteria),
|
||||
checkStarted(false) {}
|
||||
|
||||
bool SeedCheckCommand::execute() {
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
if(!seedCriteria.get()) {
|
||||
|
@ -43,7 +52,7 @@ bool SeedCheckCommand::execute() {
|
|||
}
|
||||
if(checkPoint.elapsed(1)) {
|
||||
if(!checkStarted) {
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
checkStarted = true;
|
||||
seedCriteria->reset();
|
||||
}
|
||||
|
@ -51,7 +60,7 @@ bool SeedCheckCommand::execute() {
|
|||
if(checkStarted) {
|
||||
if(seedCriteria->evaluate()) {
|
||||
logger->notice("CUID#%d - Seeding is over.", cuid);
|
||||
e->torrentMan->setHalt(true);
|
||||
btRuntime->setHalt(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,24 +35,22 @@
|
|||
#ifndef _D_SEED_CHECK_COMMAND_H_
|
||||
#define _D_SEED_CHECK_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
#include "SeedCriteria.h"
|
||||
|
||||
class SeedCheckCommand : public Command {
|
||||
class SeedCheckCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
Time checkPoint;
|
||||
SeedCriteriaHandle seedCriteria;
|
||||
bool checkStarted;
|
||||
public:
|
||||
SeedCheckCommand(int cuid, TorrentDownloadEngine* e,
|
||||
SeedCriteriaHandle seedCriteria)
|
||||
:Command(cuid),
|
||||
e(e),
|
||||
seedCriteria(seedCriteria),
|
||||
checkStarted(false) {}
|
||||
SeedCheckCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
SeedCriteriaHandle seedCriteria);
|
||||
|
||||
virtual ~SeedCheckCommand() {}
|
||||
|
||||
|
|
|
@ -36,26 +36,37 @@
|
|||
#define _D_SHARE_RATIO_SEED_CRITERIA_H_
|
||||
|
||||
#include "SeedCriteria.h"
|
||||
#include "TorrentMan.h"
|
||||
#include "BtContext.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "BtRegistry.h"
|
||||
|
||||
class ShareRatioSeedCriteria : public SeedCriteria {
|
||||
private:
|
||||
double ratio;
|
||||
TorrentMan* torrentMan;
|
||||
BtContextHandle btContext;
|
||||
PeerStorageHandle peerStorage;
|
||||
BtRuntimeHandle btRuntime;
|
||||
public:
|
||||
ShareRatioSeedCriteria(double ratio, TorrentMan* torrentMan)
|
||||
ShareRatioSeedCriteria(double ratio, const BtContextHandle& btContext)
|
||||
:ratio(ratio),
|
||||
torrentMan(torrentMan) {}
|
||||
btContext(btContext),
|
||||
peerStorage(PEER_STORAGE(btContext)),
|
||||
btRuntime(BT_RUNTIME(btContext)) {}
|
||||
|
||||
virtual ~ShareRatioSeedCriteria() {}
|
||||
|
||||
virtual void reset() {}
|
||||
|
||||
virtual bool evaluate() {
|
||||
if(torrentMan->getDownloadLength() == 0) {
|
||||
if(btContext->getTotalLength() == 0) {
|
||||
return false;
|
||||
}
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
long long int allTimeUploadLength =
|
||||
btRuntime->getUploadLengthAtStartup()+stat.getSessionUploadLength();
|
||||
return ratio <=
|
||||
((double)torrentMan->getUploadLength())/torrentMan->getDownloadLength();
|
||||
((double)allTimeUploadLength)/btContext->getTotalLength();
|
||||
}
|
||||
|
||||
void setRatio(double ratio) {
|
||||
|
|
|
@ -35,15 +35,21 @@
|
|||
#include "TorrentAutoSaveCommand.h"
|
||||
#include "Util.h"
|
||||
|
||||
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), e(e), interval(interval) {}
|
||||
TorrentAutoSaveCommand::TorrentAutoSaveCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval):
|
||||
BtContextAwareCommand(cuid, btContext),
|
||||
e(e),
|
||||
interval(interval) {}
|
||||
|
||||
TorrentAutoSaveCommand::~TorrentAutoSaveCommand() {}
|
||||
|
||||
bool TorrentAutoSaveCommand::execute() {
|
||||
if(checkPoint.elapsed(interval) || e->torrentMan->isHalt()) {
|
||||
if(checkPoint.elapsed(interval) || btRuntime->isHalt()) {
|
||||
checkPoint.reset();
|
||||
e->torrentMan->save();
|
||||
if(e->torrentMan->isHalt()) {
|
||||
btProgressInfoFile->save();
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,17 +35,22 @@
|
|||
#ifndef _D_TORRENT_AUTO_SAVE_COMMAND_H_
|
||||
#define _D_TORRENT_AUTO_SAVE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "TimeA2.h"
|
||||
#include "BtContext.h"
|
||||
|
||||
class TorrentAutoSaveCommand : public Command {
|
||||
class TorrentAutoSaveCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
int interval;
|
||||
Time checkPoint;
|
||||
public:
|
||||
TorrentAutoSaveCommand(int cuid, TorrentDownloadEngine* e, int interval);
|
||||
TorrentAutoSaveCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext,
|
||||
int interval);
|
||||
|
||||
~TorrentAutoSaveCommand();
|
||||
|
||||
bool execute();
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
/* copyright --> */
|
||||
#include "TorrentConsoleDownloadEngine.h"
|
||||
#include "Util.h"
|
||||
#include <signal.h>
|
||||
|
||||
volatile sig_atomic_t haltRequested = 0;
|
||||
|
||||
TorrentConsoleDownloadEngine::TorrentConsoleDownloadEngine() {}
|
||||
|
||||
|
@ -42,8 +45,8 @@ TorrentConsoleDownloadEngine::~TorrentConsoleDownloadEngine() {}
|
|||
void TorrentConsoleDownloadEngine::sendStatistics() {
|
||||
printf("\r ");
|
||||
printf("\r");
|
||||
if(torrentMan->downloadComplete()) {
|
||||
printf("Download Completed ");
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
printf("Download Completed.");
|
||||
} else {
|
||||
printf("%s/%sB %d%% %s D:%.2f",
|
||||
Util::llitos(downloadLength, true).c_str(),
|
||||
|
@ -55,7 +58,14 @@ void TorrentConsoleDownloadEngine::sendStatistics() {
|
|||
}
|
||||
printf(" U:%.2f(%s) %d peers",
|
||||
uploadSpeed/1024.0,
|
||||
Util::llitos(torrentMan->getUploadLength(), true).c_str(),
|
||||
torrentMan->connections);
|
||||
Util::llitos(uploadLength, true).c_str(),
|
||||
btRuntime->getConnections());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void TorrentConsoleDownloadEngine::afterEachIteration() {
|
||||
if(haltRequested) {
|
||||
btRuntime->setHalt(true);
|
||||
}
|
||||
TorrentDownloadEngine::afterEachIteration();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ protected:
|
|||
public:
|
||||
TorrentConsoleDownloadEngine();
|
||||
~TorrentConsoleDownloadEngine();
|
||||
|
||||
virtual void afterEachIteration();
|
||||
};
|
||||
|
||||
#endif // _D_TORRENT_CONSOLE_DOWNLOAD_ENGINE_H_
|
||||
|
|
|
@ -34,22 +34,35 @@
|
|||
/* copyright --> */
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "Util.h"
|
||||
#include "BtRegistry.h"
|
||||
|
||||
TorrentDownloadEngine::TorrentDownloadEngine():filenameFixed(false),
|
||||
torrentMan(NULL) {}
|
||||
TorrentDownloadEngine::TorrentDownloadEngine():
|
||||
filenameFixed(false),
|
||||
btContext(0),
|
||||
btRuntime(0),
|
||||
pieceStorage(0),
|
||||
peerStorage(0),
|
||||
btAnnounce(0),
|
||||
btProgressInfoFile(0) {}
|
||||
|
||||
TorrentDownloadEngine::~TorrentDownloadEngine() {
|
||||
if(torrentMan != NULL) {
|
||||
delete torrentMan;
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentDownloadEngine::setBtContext(const BtContextHandle& btContext) {
|
||||
this->btContext = btContext;
|
||||
btRuntime = BT_RUNTIME(btContext);
|
||||
pieceStorage = PIECE_STORAGE(btContext);
|
||||
peerStorage = PEER_STORAGE(btContext);
|
||||
btAnnounce = BT_ANNOUNCE(btContext);
|
||||
btProgressInfoFile = BT_PROGRESS_INFO_FILE(btContext);
|
||||
}
|
||||
|
||||
void TorrentDownloadEngine::onEndOfRun() {
|
||||
torrentMan->diskAdaptor->closeFile();
|
||||
if(torrentMan->downloadComplete()) {
|
||||
torrentMan->remove();
|
||||
pieceStorage->getDiskAdaptor()->closeFile();
|
||||
if(pieceStorage->downloadFinished()) {
|
||||
btProgressInfoFile->removeFile();
|
||||
} else {
|
||||
torrentMan->save();
|
||||
btProgressInfoFile->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,16 +70,12 @@ void TorrentDownloadEngine::initStatistics() {
|
|||
downloadSpeed = 0;
|
||||
uploadSpeed = 0;
|
||||
cp.reset();
|
||||
lastCalcStat.reset();
|
||||
startup.reset();
|
||||
eta = 0;
|
||||
avgSpeed = 0;
|
||||
downloadLength = 0;
|
||||
uploadLength = 0;
|
||||
totalLength = 0;
|
||||
if(torrentMan->isSelectiveDownloadingMode()) {
|
||||
selectedDownloadLengthDiff = torrentMan->getDownloadLength()-torrentMan->getCompletedLength();
|
||||
selectedTotalLength = torrentMan->getSelectedTotalLength();
|
||||
}
|
||||
}
|
||||
|
||||
int TorrentDownloadEngine::calculateSpeed(long long int length, int elapsed) {
|
||||
|
@ -75,10 +84,22 @@ int TorrentDownloadEngine::calculateSpeed(long long int length, int elapsed) {
|
|||
}
|
||||
|
||||
void TorrentDownloadEngine::calculateStat() {
|
||||
TransferStat stat = torrentMan->calculateStat();
|
||||
downloadSpeed = stat.downloadSpeed;
|
||||
uploadSpeed = stat.uploadSpeed;
|
||||
avgSpeed = calculateSpeed(stat.sessionDownloadLength, startup.difference());
|
||||
TransferStat stat = peerStorage->calculateStat();
|
||||
|
||||
if(pieceStorage->isSelectiveDownloadingMode()) {
|
||||
downloadLength = pieceStorage->getFilteredCompletedLength();
|
||||
totalLength = pieceStorage->getFilteredTotalLength();
|
||||
} else {
|
||||
downloadLength = pieceStorage->getCompletedLength();
|
||||
totalLength = pieceStorage->getTotalLength();
|
||||
}
|
||||
uploadLength = stat.getSessionUploadLength()+
|
||||
btRuntime->getUploadLengthAtStartup();
|
||||
|
||||
downloadSpeed = stat.getDownloadSpeed();
|
||||
uploadSpeed = stat.getUploadSpeed();
|
||||
avgSpeed = calculateSpeed(stat.getSessionDownloadLength(),
|
||||
startup.difference());
|
||||
if(avgSpeed < 0) {
|
||||
avgSpeed = 0;
|
||||
} else if(avgSpeed != 0) {
|
||||
|
@ -87,20 +108,8 @@ void TorrentDownloadEngine::calculateStat() {
|
|||
}
|
||||
|
||||
void TorrentDownloadEngine::calculateStatistics() {
|
||||
if(torrentMan->isSelectiveDownloadingMode()) {
|
||||
downloadLength = torrentMan->getDownloadLength()-selectedDownloadLengthDiff;
|
||||
totalLength = selectedTotalLength;
|
||||
} else {
|
||||
downloadLength = torrentMan->getDownloadLength();
|
||||
totalLength = torrentMan->getTotalLength();
|
||||
}
|
||||
|
||||
Time now;
|
||||
if(now.getTimeInMillis()-lastCalcStat.getTimeInMillis() >= 1000) {
|
||||
calculateStat();
|
||||
lastCalcStat = now;
|
||||
}
|
||||
if(cp.difference() >= 1) {
|
||||
calculateStat();
|
||||
sendStatistics();
|
||||
cp.reset();
|
||||
}
|
||||
|
|
|
@ -36,8 +36,13 @@
|
|||
#define _D_TORRENT_DOWNLOAD_ENGINE_H_
|
||||
|
||||
#include "DownloadEngine.h"
|
||||
#include "TorrentMan.h"
|
||||
#include "TimeA2.h"
|
||||
#include "BtContext.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
|
||||
class TorrentDownloadEngine : public DownloadEngine {
|
||||
private:
|
||||
|
@ -59,8 +64,16 @@ protected:
|
|||
// The estimated remaining time to complete the download.
|
||||
int eta;
|
||||
long long int downloadLength;
|
||||
long long int uploadLength;
|
||||
long long int totalLength;
|
||||
|
||||
BtContextHandle btContext;
|
||||
BtRuntimeHandle btRuntime;
|
||||
PieceStorageHandle pieceStorage;
|
||||
PeerStorageHandle peerStorage;
|
||||
BtAnnounceHandle btAnnounce;
|
||||
BtProgressInfoFileHandle btProgressInfoFile;
|
||||
|
||||
int calculateSpeed(long long int sessionLength, int elapsed);
|
||||
void calculateStat();
|
||||
|
||||
|
@ -70,9 +83,9 @@ public:
|
|||
TorrentDownloadEngine();
|
||||
virtual ~TorrentDownloadEngine();
|
||||
|
||||
TorrentMan* torrentMan;
|
||||
|
||||
bool isFilenameFixed() const { return filenameFixed; }
|
||||
|
||||
void setBtContext(const BtContextHandle& btContext);
|
||||
};
|
||||
|
||||
#endif // _D_TORRENT_DOWNLOAD_ENGINE_H_
|
||||
|
|
|
@ -36,19 +36,24 @@
|
|||
#include "DownloadEngineFactory.h"
|
||||
#include "prefs.h"
|
||||
#include "Util.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "DefaultBtContext.h"
|
||||
|
||||
extern RequestInfo* requestInfo;
|
||||
extern void setSignalHander(int signal, void (*handler)(int), int flags);
|
||||
extern bool timeoutSpecified;
|
||||
extern volatile sig_atomic_t haltRequested;
|
||||
|
||||
void torrentHandler(int signal) {
|
||||
((TorrentDownloadEngine*)requestInfo->getDownloadEngine())->
|
||||
torrentMan->setHalt(true);
|
||||
haltRequested = 1;
|
||||
}
|
||||
|
||||
RequestInfo* TorrentRequestInfo::execute() {
|
||||
BtContextHandle btContext(new DefaultBtContext());
|
||||
btContext->load(torrentFile);
|
||||
|
||||
if(op->get(PREF_SHOW_FILES) == V_TRUE) {
|
||||
showFileEntry();
|
||||
showFileEntry(btContext);
|
||||
return 0;
|
||||
}
|
||||
if(!timeoutSpecified) {
|
||||
|
@ -56,45 +61,42 @@ RequestInfo* TorrentRequestInfo::execute() {
|
|||
}
|
||||
// set max_tries to 1. AnnounceList handles retries.
|
||||
op->put(PREF_MAX_TRIES, "1");
|
||||
e = DownloadEngineFactory::newTorrentConsoleEngine(op,
|
||||
torrentFile,
|
||||
targetFiles);
|
||||
SharedHandle<TorrentDownloadEngine>
|
||||
e(DownloadEngineFactory::newTorrentConsoleEngine(btContext,
|
||||
op,
|
||||
targetFiles));
|
||||
|
||||
setSignalHander(SIGINT, torrentHandler, SA_RESETHAND);
|
||||
setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND);
|
||||
|
||||
try {
|
||||
e->run();
|
||||
if(e->torrentMan->downloadComplete()) {
|
||||
if(PIECE_STORAGE(btContext)->downloadFinished()) {
|
||||
printDownloadCompeleteMessage();
|
||||
}
|
||||
} catch(Exception* e) {
|
||||
logger->error("Exception caught", e);
|
||||
delete e;
|
||||
} catch(Exception* ex) {
|
||||
logger->error("Exception caught", ex);
|
||||
fail = true;
|
||||
delete ex;
|
||||
}
|
||||
setSignalHander(SIGINT, SIG_DFL, 0);
|
||||
setSignalHander(SIGTERM, SIG_DFL, 0);
|
||||
delete e;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO should be const TorrentMan* torrentMan
|
||||
void TorrentRequestInfo::showFileEntry()
|
||||
void TorrentRequestInfo::showFileEntry(const BtContextHandle& btContext)
|
||||
{
|
||||
TorrentMan torrentMan;
|
||||
torrentMan.option = op;
|
||||
|
||||
FileEntries fileEntries =
|
||||
torrentMan.readFileEntryFromMetaInfoFile(torrentFile);
|
||||
FileEntries fileEntries = btContext->getFileEntries();
|
||||
cout << _("Files:") << endl;
|
||||
cout << "idx|path/length" << endl;
|
||||
cout << "===+===========================================================================" << endl;
|
||||
int count = 1;
|
||||
for(FileEntries::const_iterator itr = fileEntries.begin();
|
||||
itr != fileEntries.end(); count++, itr++) {
|
||||
printf("%3d|%s\n |%s Bytes\n", count, itr->path.c_str(),
|
||||
Util::llitos(itr->length, true).c_str());
|
||||
printf("%3d|%s\n |%s Bytes\n", count,
|
||||
(*itr)->getPath().c_str(),
|
||||
Util::llitos((*itr)->getLength(), true).c_str());
|
||||
cout << "---+---------------------------------------------------------------------------" << endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,19 +37,19 @@
|
|||
|
||||
#include "RequestInfo.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "BtContext.h"
|
||||
|
||||
class TorrentRequestInfo : public RequestInfo {
|
||||
private:
|
||||
string torrentFile;
|
||||
TorrentDownloadEngine* e;
|
||||
Strings targetFiles;
|
||||
|
||||
void showFileEntry();
|
||||
void showFileEntry(const BtContextHandle& btContext);
|
||||
public:
|
||||
TorrentRequestInfo(const string& torrentFile, Option* op):
|
||||
RequestInfo(op),
|
||||
torrentFile(torrentFile),
|
||||
e(0) {}
|
||||
torrentFile(torrentFile) {}
|
||||
|
||||
virtual ~TorrentRequestInfo() {}
|
||||
|
||||
virtual RequestInfo* execute();
|
||||
|
@ -57,8 +57,10 @@ public:
|
|||
void setTargetFiles(const Strings& targetFiles) {
|
||||
this->targetFiles = targetFiles;
|
||||
}
|
||||
virtual DownloadEngine* getDownloadEngine() { return e; }
|
||||
|
||||
virtual DownloadEngine* getDownloadEngine() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _D_TORRENT_REQUEST_INFO_H_
|
||||
|
|
|
@ -40,7 +40,13 @@
|
|||
#include "SleepCommand.h"
|
||||
#include "Util.h"
|
||||
|
||||
TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e):Command(cuid), e(e) {
|
||||
extern PeerHandle nullPeer;
|
||||
|
||||
TrackerUpdateCommand::TrackerUpdateCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext):
|
||||
BtContextAwareCommand(cuid, btContext), e(e)
|
||||
{
|
||||
logger = LogFactory::getInstance();
|
||||
}
|
||||
|
||||
|
@ -77,7 +83,7 @@ char* TrackerUpdateCommand::getTrackerResponse(size_t& trackerResponseLength) {
|
|||
}
|
||||
|
||||
bool TrackerUpdateCommand::execute() {
|
||||
if(e->segmentMan->errors > 0 && e->torrentMan->isHalt()) {
|
||||
if(e->segmentMan->errors > 0 && btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
if(!e->segmentMan->finished()) {
|
||||
|
@ -89,19 +95,25 @@ bool TrackerUpdateCommand::execute() {
|
|||
try {
|
||||
trackerResponse = getTrackerResponse(trackerResponseLength);
|
||||
|
||||
e->torrentMan->processAnnounceResponse(trackerResponse,
|
||||
trackerResponseLength);
|
||||
while(e->torrentMan->needMorePeerConnection()) {
|
||||
PeerHandle peer = e->torrentMan->getPeer();
|
||||
int newCuid = e->torrentMan->getNewCuid();
|
||||
btAnnounce->processAnnounceResponse(trackerResponse,
|
||||
trackerResponseLength);
|
||||
while(!btRuntime->isHalt() && btRuntime->lessThanMinPeer()) {
|
||||
PeerHandle peer = peerStorage->getUnusedPeer();
|
||||
if(peer == nullPeer) {
|
||||
break;
|
||||
}
|
||||
int newCuid = btRuntime->getNewCuid();
|
||||
peer->cuid = newCuid;
|
||||
PeerInitiateConnectionCommand* command =
|
||||
new PeerInitiateConnectionCommand(newCuid, peer, e);
|
||||
new PeerInitiateConnectionCommand(newCuid,
|
||||
peer,
|
||||
e,
|
||||
btContext);
|
||||
e->commands.push_back(command);
|
||||
logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid);
|
||||
}
|
||||
e->torrentMan->announceSuccess();
|
||||
e->torrentMan->resetAnnounce();
|
||||
btAnnounce->announceSuccess();
|
||||
btAnnounce->resetAnnounce();
|
||||
e->segmentMan->init();
|
||||
} catch(Exception* err) {
|
||||
logger->error("CUID#%d - Error occurred while processing tracker response.", cuid, err);
|
||||
|
@ -111,7 +123,7 @@ bool TrackerUpdateCommand::execute() {
|
|||
if(trackerResponse) {
|
||||
delete [] trackerResponse;
|
||||
}
|
||||
if(e->torrentMan->isHalt()) {
|
||||
if(btRuntime->isHalt()) {
|
||||
return true;
|
||||
} else {
|
||||
return prepareForRetry();
|
||||
|
|
|
@ -35,18 +35,21 @@
|
|||
#ifndef _D_TRACKER_UPDATE_COMMAND_H_
|
||||
#define _D_TRACKER_UPDATE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
#include "Logger.h"
|
||||
|
||||
class TrackerUpdateCommand : public Command {
|
||||
class TrackerUpdateCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
const Logger* logger;
|
||||
bool prepareForRetry();
|
||||
char* getTrackerResponse(size_t& trackerResponseLength);
|
||||
public:
|
||||
TrackerUpdateCommand(int cuid, TorrentDownloadEngine* e);
|
||||
TrackerUpdateCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext);
|
||||
|
||||
virtual ~TrackerUpdateCommand();
|
||||
|
||||
bool execute();
|
||||
|
|
|
@ -39,17 +39,19 @@
|
|||
#include "prefs.h"
|
||||
|
||||
TrackerWatcherCommand::TrackerWatcherCommand(int cuid,
|
||||
TorrentDownloadEngine* e):
|
||||
Command(cuid), e(e) {
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext):
|
||||
BtContextAwareCommand(cuid, btContext), e(e)
|
||||
{
|
||||
}
|
||||
|
||||
TrackerWatcherCommand::~TrackerWatcherCommand() {}
|
||||
|
||||
|
||||
bool TrackerWatcherCommand::execute() {
|
||||
if(e->torrentMan->isHalt() &&
|
||||
e->segmentMan->errors > 0 && e->torrentMan->isAllAnnounceFailed() ||
|
||||
e->torrentMan->noMoreAnnounce()) {
|
||||
if(btRuntime->isHalt() &&
|
||||
e->segmentMan->errors > 0 && btAnnounce->isAllAnnounceFailed() ||
|
||||
btAnnounce->noMoreAnnounce()) {
|
||||
return true;
|
||||
}
|
||||
Command* command = createCommand();
|
||||
|
@ -62,18 +64,18 @@ bool TrackerWatcherCommand::execute() {
|
|||
|
||||
Command* TrackerWatcherCommand::createCommand() {
|
||||
Command* command = 0;
|
||||
if(e->torrentMan->isAnnounceReady()) {
|
||||
command = createRequestCommand(e->torrentMan->getAnnounceUrl());
|
||||
e->torrentMan->announceStart(); // inside it, trackers++.
|
||||
if(btAnnounce->isAnnounceReady()) {
|
||||
command = createRequestCommand(btAnnounce->getAnnounceUrl());
|
||||
btAnnounce->announceStart(); // inside it, trackers++.
|
||||
} else if(e->segmentMan->errors > 0) {
|
||||
e->torrentMan->announceFailure(); // inside it, trackers = 0.
|
||||
btAnnounce->announceFailure(); // inside it, trackers = 0.
|
||||
e->segmentMan->init();
|
||||
if(e->torrentMan->isAllAnnounceFailed()) {
|
||||
e->torrentMan->resetAnnounce();
|
||||
if(btAnnounce->isAllAnnounceFailed()) {
|
||||
btAnnounce->resetAnnounce();
|
||||
// sleep a few seconds.
|
||||
command =
|
||||
new SleepCommand(cuid, e,
|
||||
createRequestCommand(e->torrentMan->getAnnounceUrl()),
|
||||
createRequestCommand(btAnnounce->getAnnounceUrl()),
|
||||
e->option->getAsInt(PREF_RETRY_WAIT));
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +86,8 @@ Command* TrackerWatcherCommand::createRequestCommand(const string& url) {
|
|||
RequestHandle req;
|
||||
req->setUrl(url);
|
||||
req->isTorrent = true;
|
||||
Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(e->torrentMan->getNewCuid(), req, e);
|
||||
Command* command =
|
||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand(btRuntime->getNewCuid(), req, e);
|
||||
logger->info("CUID#%d - Creating new tracker request command #%d", cuid,
|
||||
command->getCuid());
|
||||
return command;
|
||||
|
|
|
@ -35,10 +35,10 @@
|
|||
#ifndef _D_TRACKER_WATCHER_COMMAND_H_
|
||||
#define _D_TRACKER_WATCHER_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "BtContextAwareCommand.h"
|
||||
#include "TorrentDownloadEngine.h"
|
||||
|
||||
class TrackerWatcherCommand : public Command {
|
||||
class TrackerWatcherCommand : public BtContextAwareCommand {
|
||||
private:
|
||||
TorrentDownloadEngine* e;
|
||||
|
||||
|
@ -48,7 +48,10 @@ private:
|
|||
*/
|
||||
Command* createRequestCommand(const string& url);
|
||||
public:
|
||||
TrackerWatcherCommand(int cuid, TorrentDownloadEngine* e);
|
||||
TrackerWatcherCommand(int cuid,
|
||||
TorrentDownloadEngine* e,
|
||||
const BtContextHandle& btContext);
|
||||
|
||||
~TrackerWatcherCommand();
|
||||
|
||||
Command* createCommand();
|
||||
|
|
16
src/Util.cc
16
src/Util.cc
|
@ -117,20 +117,28 @@ int Util::difftvsec(struct timeval tv1, struct timeval tv2) {
|
|||
return tv1.tv_sec-tv2.tv_sec;
|
||||
}
|
||||
|
||||
void Util::slice(Strings& result, const string& src, char delim) {
|
||||
void Util::slice(Strings& result, const string& src, char delim, bool doTrim) {
|
||||
string::size_type p = 0;
|
||||
while(1) {
|
||||
string::size_type np = src.find(delim, p);
|
||||
if(np == string::npos) {
|
||||
string term = trim(src.substr(p));
|
||||
if(term.size() > 0) {
|
||||
string term = src.substr(p);
|
||||
if(doTrim) {
|
||||
term = trim(term);
|
||||
}
|
||||
if(term.size()) {
|
||||
result.push_back(term);
|
||||
}
|
||||
break;
|
||||
}
|
||||
string term = src.substr(p, np-p);
|
||||
if(doTrim) {
|
||||
term = trim(term);
|
||||
}
|
||||
p = np+1;
|
||||
result.push_back(trim(term));
|
||||
if(term.size()) {
|
||||
result.push_back(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
* Take a string src which is a deliminated list and add its elements
|
||||
* into result. result is not cleared before conversion begins.
|
||||
*/
|
||||
static void slice(Strings& result, const string& src, char delim);
|
||||
static void slice(Strings& result, const string& src, char delim, bool trim = false);
|
||||
|
||||
static string trim(const string& src);
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#include "SharedHandle.h"
|
||||
|
||||
typedef deque<string> Strings;
|
||||
typedef deque<int> Integers;
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ void showVersion() {
|
|||
"along with this program; if not, write to the Free Software\n"
|
||||
"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n");
|
||||
cout << endl;
|
||||
printf(_("Contact Info: %s\n"), "Tasuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>");
|
||||
printf(_("Contact Info: %s\n"), "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>");
|
||||
cout << endl;
|
||||
|
||||
}
|
||||
|
|
|
@ -227,10 +227,10 @@ Strings createUrls(const string& url) {
|
|||
}
|
||||
|
||||
void AnnounceListTest::testMoveToStoppedAllowedTier() {
|
||||
AnnounceTier t1(createUrls("tracker1"));
|
||||
AnnounceTier t2(createUrls("tracker2"));
|
||||
t2.event = AnnounceTier::COMPLETED;
|
||||
AnnounceTier t3(createUrls("tracker3"));
|
||||
AnnounceTierHandle t1(new AnnounceTier(createUrls("tracker1")));
|
||||
AnnounceTierHandle t2(new AnnounceTier(createUrls("tracker2")));
|
||||
t2->event = AnnounceTier::COMPLETED;
|
||||
AnnounceTierHandle t3(new AnnounceTier(createUrls("tracker3")));
|
||||
|
||||
AnnounceTiers tiers;
|
||||
tiers.push_back(t1);
|
||||
|
@ -250,10 +250,10 @@ void AnnounceListTest::testMoveToStoppedAllowedTier() {
|
|||
}
|
||||
|
||||
void AnnounceListTest::testMoveToCompletedAllowedTier() {
|
||||
AnnounceTier t1(createUrls("tracker1"));
|
||||
AnnounceTier t2(createUrls("tracker2"));
|
||||
t2.event = AnnounceTier::COMPLETED;
|
||||
AnnounceTier t3(createUrls("tracker3"));
|
||||
AnnounceTierHandle t1(new AnnounceTier(createUrls("tracker1")));
|
||||
AnnounceTierHandle t2(new AnnounceTier(createUrls("tracker2")));
|
||||
t2->event = AnnounceTier::COMPLETED;
|
||||
AnnounceTierHandle t3(new AnnounceTier(createUrls("tracker3")));
|
||||
|
||||
AnnounceTiers tiers;
|
||||
tiers.push_back(t1);
|
||||
|
|
|
@ -95,21 +95,21 @@ void BitfieldManTest::testFilter() {
|
|||
int index;
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(2, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(3, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(4, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(2, index);
|
||||
CPPUNIT_ASSERT_EQUAL(5, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(6, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(5, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(7, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
|
@ -118,17 +118,18 @@ void BitfieldManTest::testFilter() {
|
|||
|
||||
// test offset=5, length=2
|
||||
btman.clearAllBit();
|
||||
btman.clearAllUseBit();
|
||||
btman.clearFilter();
|
||||
btman.addFilter(5, 2);
|
||||
btman.enableFilter();
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
btman.setBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(3, index);
|
||||
CPPUNIT_ASSERT_EQUAL(2, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
btman.setBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(2, index);
|
||||
CPPUNIT_ASSERT_EQUAL(3, index);
|
||||
index = btman.getMissingUnusedIndex(peerBt, sizeof(peerBt));
|
||||
btman.setUseBit(index);
|
||||
CPPUNIT_ASSERT_EQUAL(-1, index);
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
#include "BtRegistry.h"
|
||||
#include "Exception.h"
|
||||
#include "MockPeerStorage.h"
|
||||
#include "MockPieceStorage.h"
|
||||
#include "MockBtAnnounce.h"
|
||||
#include "MockBtProgressInfoFile.h"
|
||||
#include <string>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BtRegistryTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(BtRegistryTest);
|
||||
CPPUNIT_TEST(testGetPeerStorage);
|
||||
CPPUNIT_TEST(testGetPieceStorage);
|
||||
CPPUNIT_TEST(testGetBtRuntime);
|
||||
CPPUNIT_TEST(testGetBtAnnounce);
|
||||
CPPUNIT_TEST(testGetBtProgressInfoFile);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
|
||||
public:
|
||||
void setUp() {
|
||||
}
|
||||
|
||||
void testGetPeerStorage();
|
||||
void testGetPieceStorage();
|
||||
void testGetBtRuntime();
|
||||
void testGetBtAnnounce();
|
||||
void testGetBtProgressInfoFile();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( BtRegistryTest );
|
||||
|
||||
void BtRegistryTest::testGetPeerStorage() {
|
||||
CPPUNIT_ASSERT(!BtRegistry::getPeerStorage("test").get());
|
||||
|
||||
PeerStorageHandle peerStorage(new MockPeerStorage());
|
||||
|
||||
CPPUNIT_ASSERT(BtRegistry::registerPeerStorage("test",
|
||||
peerStorage));
|
||||
CPPUNIT_ASSERT_EQUAL(peerStorage.get(),
|
||||
BtRegistry::getPeerStorage("test").get());
|
||||
}
|
||||
|
||||
void BtRegistryTest::testGetPieceStorage() {
|
||||
CPPUNIT_ASSERT(!BtRegistry::getPieceStorage("test").get());
|
||||
|
||||
PieceStorageHandle pieceStorage(new MockPieceStorage());
|
||||
|
||||
CPPUNIT_ASSERT(BtRegistry::registerPieceStorage("test",
|
||||
pieceStorage));
|
||||
CPPUNIT_ASSERT_EQUAL(pieceStorage.get(),
|
||||
BtRegistry::getPieceStorage("test").get());
|
||||
}
|
||||
|
||||
void BtRegistryTest::testGetBtRuntime() {
|
||||
CPPUNIT_ASSERT(!BtRegistry::getBtRuntime("test").get());
|
||||
|
||||
BtRuntimeHandle runtime;
|
||||
|
||||
CPPUNIT_ASSERT(BtRegistry::registerBtRuntime("test", runtime));
|
||||
CPPUNIT_ASSERT_EQUAL(runtime.get(),
|
||||
BtRegistry::getBtRuntime("test").get());
|
||||
}
|
||||
|
||||
void BtRegistryTest::testGetBtAnnounce() {
|
||||
CPPUNIT_ASSERT(!BtRegistry::getBtAnnounce("test").get());
|
||||
|
||||
BtAnnounceHandle btAnnounce(new MockBtAnnounce());
|
||||
|
||||
CPPUNIT_ASSERT(BtRegistry::registerBtAnnounce("test", btAnnounce));
|
||||
CPPUNIT_ASSERT_EQUAL(btAnnounce.get(),
|
||||
BtRegistry::getBtAnnounce("test").get());
|
||||
}
|
||||
|
||||
void BtRegistryTest::testGetBtProgressInfoFile() {
|
||||
CPPUNIT_ASSERT(!BtRegistry::getBtProgressInfoFile("test").get());
|
||||
|
||||
BtProgressInfoFileHandle btProgressInfoFile(new MockBtProgressInfoFile());
|
||||
|
||||
CPPUNIT_ASSERT(BtRegistry::registerBtProgressInfoFile("test",
|
||||
btProgressInfoFile));
|
||||
CPPUNIT_ASSERT_EQUAL(btProgressInfoFile.get(),
|
||||
BtRegistry::getBtProgressInfoFile("test").get());
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue