/* */ #include "TrackerWatcherCommand.h" #include "DownloadEngine.h" #include "Util.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 "RequestGroup.h" #include "Option.h" #include "DlRetryEx.h" #include "DlAbortEx.h" TrackerWatcherCommand::TrackerWatcherCommand(int32_t cuid, RequestGroup* requestGroup, DownloadEngine* e, const BtContextHandle& btContext): Command(cuid), BtContextAwareCommand(btContext), RequestGroupAware(requestGroup), e(e), _trackerRequestGroup(0) { } 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()) { e->addCommand(_trackerRequestGroup->createInitialCommand(e)); logger->debug("added tracker request command"); } } else if(_trackerRequestGroup->downloadFinished()){ try { string trackerResponse = getTrackerResponse(_trackerRequestGroup); processTrackerResponse(trackerResponse); btAnnounce->announceSuccess(); btAnnounce->resetAnnounce(); } catch(RecoverableException* ex) { logger->error(EX_EXCEPTION_CAUGHT, ex); delete ex; btAnnounce->announceFailure(); if(btAnnounce->isAllAnnounceFailed()) { btAnnounce->resetAnnounce(); } } _trackerRequestGroup = 0; } else if(_trackerRequestGroup->getNumCommand() == 0){ // handle errors here btAnnounce->announceFailure(); // inside it, trackers = 0. _trackerRequestGroup = 0; if(btAnnounce->isAllAnnounceFailed()) { btAnnounce->resetAnnounce(); } } e->commands.push_back(this); return false; } string TrackerWatcherCommand::getTrackerResponse(const RequestGroupHandle& requestGroup) { stringstream strm; char data[2048]; requestGroup->getPieceStorage()->getDiskAdaptor()->openFile(); while(1) { int32_t dataLength = requestGroup->getPieceStorage()->getDiskAdaptor()->readData((unsigned char*)data, sizeof(data), strm.tellp()); strm.write(data, dataLength); if(dataLength == 0) { break; } } return strm.str(); } // TODO we have to deal with the exception thrown By BtAnnounce void TrackerWatcherCommand::processTrackerResponse(const string& trackerResponse) { btAnnounce->processAnnounceResponse(trackerResponse.c_str(), trackerResponse.size()); while(!btRuntime->isHalt() && btRuntime->lessThanMinPeer()) { PeerHandle peer = peerStorage->getUnusedPeer(); if(peer.isNull()) { break; } peer->cuid = CUIDCounterSingletonHolder::instance()->newID(); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->cuid, _requestGroup, peer, e, btContext); e->commands.push_back(command); logger->debug("CUID#%d - Adding new command CUID#%d", cuid, peer->cuid); } } RequestGroupHandle TrackerWatcherCommand::createAnnounce() { RequestGroupHandle rg = 0; if(btAnnounce->isAnnounceReady()) { rg = createRequestGroup(btAnnounce->getAnnounceUrl()); btAnnounce->announceStart(); // inside it, trackers++. } return rg; } RequestGroupHandle TrackerWatcherCommand::createRequestGroup(const string& uri) { Strings uris; uris.push_back(uri); RequestGroupHandle rg = new RequestGroup(e->option, uris); SingleFileDownloadContextHandle dctx = new SingleFileDownloadContext(e->option->getAsInt(PREF_SEGMENT_SIZE), 0, "", "[tracker.announce]"); dctx->setDir(""); rg->setDownloadContext(dctx); rg->setDiskWriterFactory(new ByteArrayDiskWriterFactory()); rg->setFileAllocationEnabled(false); rg->setPreLocalFileCheckEnabled(false); logger->info("Creating tracker request group GID#%d", rg->getGID()); return rg; }