/* */ #include "TrackerWatcherCommand.h" #include "DownloadEngine.h" #include "BtContext.h" #include "BtAnnounce.h" #include "BtRuntime.h" #include "PieceStorage.h" #include "PeerStorage.h" #include "Peer.h" #include "prefs.h" #include "message.h" #include "SingleFileDownloadContext.h" #include "ByteArrayDiskWriterFactory.h" #include "RecoverableException.h" #include "CUIDCounter.h" #include "PeerInitiateConnectionCommand.h" #include "DiskAdaptor.h" #include "FileEntry.h" #include "RequestGroup.h" #include "Option.h" #include "DlAbortEx.h" #include "Logger.h" #include "A2STR.h" #include "SocketCore.h" #include namespace aria2 { TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const BtContextHandle& btContext): Command(cuid), BtContextAwareCommand(btContext), RequestGroupAware(requestGroup), e(e) {} TrackerWatcherCommand::~TrackerWatcherCommand() {} bool TrackerWatcherCommand::execute() { if(_requestGroup->isForceHaltRequested()) { if(_trackerRequestGroup.isNull()) { return true; } else if(_trackerRequestGroup->getNumCommand() == 0 || _trackerRequestGroup->downloadFinished()) { return true; } else { _trackerRequestGroup->setForceHaltRequested(true); return false; } } if(btAnnounce->noMoreAnnounce()) { logger->debug("no more announce"); return true; } if(_trackerRequestGroup.isNull()) { _trackerRequestGroup = createAnnounce(); if(!_trackerRequestGroup.isNull()) { std::deque commands; _trackerRequestGroup->createInitialCommand(commands, e); e->addCommand(commands); logger->debug("added tracker request command"); } } else if(_trackerRequestGroup->downloadFinished()){ try { std::string trackerResponse = getTrackerResponse(_trackerRequestGroup); processTrackerResponse(trackerResponse); btAnnounce->announceSuccess(); btAnnounce->resetAnnounce(); } catch(RecoverableException& ex) { logger->error(EX_EXCEPTION_CAUGHT, ex); btAnnounce->announceFailure(); if(btAnnounce->isAllAnnounceFailed()) { btAnnounce->resetAnnounce(); } } _trackerRequestGroup.reset(); } else if(_trackerRequestGroup->getNumCommand() == 0){ // handle errors here btAnnounce->announceFailure(); // inside it, trackers = 0. _trackerRequestGroup.reset(); if(btAnnounce->isAllAnnounceFailed()) { btAnnounce->resetAnnounce(); } } e->commands.push_back(this); return false; } std::string TrackerWatcherCommand::getTrackerResponse(const RequestGroupHandle& requestGroup) { std::stringstream strm; unsigned char data[2048]; requestGroup->getPieceStorage()->getDiskAdaptor()->openFile(); while(1) { ssize_t dataLength = requestGroup->getPieceStorage()->getDiskAdaptor()->readData(data, sizeof(data), strm.tellp()); if(dataLength == 0) { break; } strm.write(reinterpret_cast(data), dataLength); } return strm.str(); } // TODO we have to deal with the exception thrown By BtAnnounce void TrackerWatcherCommand::processTrackerResponse(const std::string& trackerResponse) { btAnnounce->processAnnounceResponse(reinterpret_cast(trackerResponse.c_str()), trackerResponse.size()); while(!btRuntime->isHalt() && btRuntime->lessThanMinPeers()) { PeerHandle peer = peerStorage->getUnusedPeer(); if(peer.isNull()) { break; } peer->usedBy(CUIDCounterSingletonHolder::instance()->newID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e, btContext); e->commands.push_back(command); logger->debug("CUID#%d - Adding new command CUID#%d", cuid, peer->usedBy()); } } RequestGroupHandle TrackerWatcherCommand::createAnnounce() { RequestGroupHandle rg; if(btAnnounce->isAnnounceReady()) { rg = createRequestGroup(btAnnounce->getAnnounceUrl()); btAnnounce->announceStart(); // inside it, trackers++. } return rg; } RequestGroupHandle TrackerWatcherCommand::createRequestGroup(const std::string& uri) { std::deque uris; uris.push_back(uri); RequestGroupHandle rg(new RequestGroup(e->option, uris)); static const std::string TRACKER_ANNOUNCE_FILE("[tracker.announce]"); SingleFileDownloadContextHandle dctx (new SingleFileDownloadContext(e->option->getAsInt(PREF_SEGMENT_SIZE), 0, A2STR::NIL, TRACKER_ANNOUNCE_FILE)); dctx->setDir(A2STR::NIL); rg->setDownloadContext(dctx); SharedHandle dwf(new ByteArrayDiskWriterFactory()); rg->setDiskWriterFactory(dwf); rg->setFileAllocationEnabled(false); rg->setPreLocalFileCheckEnabled(false); logger->info("Creating tracker request group GID#%d", rg->getGID()); return rg; } } // namespace aria2