/* */ #include "TrackerUpdateCommand.h" #include "LogFactory.h" #include "MetaFileUtil.h" #include "DlAbortEx.h" #include "message.h" #include "PeerInitiateConnectionCommand.h" #include "SleepCommand.h" #include "Util.h" #include "DelegatingPeerListProcessor.h" TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine*e):Command(cuid), e(e) { logger = LogFactory::getInstance(); } TrackerUpdateCommand::~TrackerUpdateCommand() {} bool TrackerUpdateCommand::prepareForRetry() { e->commands.push_back(this); return false; } char* TrackerUpdateCommand::getTrackerResponse(int& trackerResponseLength) { int maxBufLength = 2048; char* buf = new char[maxBufLength]; int bufLength = 0; char data[2048]; try { while(1) { int dataLength = e->segmentMan->diskWriter->readData(data, sizeof(data), bufLength); if(bufLength+dataLength >= maxBufLength) { maxBufLength = Util::expandBuffer(&buf, bufLength, bufLength+dataLength); } memcpy(buf+bufLength, data, dataLength); bufLength += dataLength; if(dataLength != sizeof(data)) { break; } } trackerResponseLength = bufLength; return buf; } catch(Exception* e) { delete [] buf; throw; } } bool TrackerUpdateCommand::execute() { if(e->segmentMan->errors > 0 && e->torrentMan->isHalt()) { return true; } if(!e->segmentMan->finished()) { return prepareForRetry(); } char* trackerResponse = NULL; int trackerResponseLength = 0; try { trackerResponse = getTrackerResponse(trackerResponseLength); SharedHandle entry(MetaFileUtil::bdecoding(trackerResponse, trackerResponseLength)); Dictionary* response = (Dictionary*)entry.get(); Data* failureReason = (Data*)response->get("failure reason"); if(failureReason != NULL) { throw new DlAbortEx("Tracker returned failure reason: %s", failureReason->toString().c_str()); } Data* warningMessage = (Data*)response->get("warning message"); if(warningMessage != NULL) { logger->warn(MSG_TRACKER_WARNING_MESSAGE, warningMessage->toString().c_str()); } Data* trackerId = (Data*)response->get("tracker id"); if(trackerId != NULL) { e->torrentMan->trackerId = trackerId->toString(); logger->debug("CUID#%d - Tracker ID:%s", cuid, e->torrentMan->trackerId.c_str()); } Data* interval = (Data*)response->get("interval"); if(interval != NULL) { e->torrentMan->interval = interval->toInt(); logger->debug("CUID#%d - Interval:%d", cuid, e->torrentMan->interval); } Data* minInterval = (Data*)response->get("min interval"); if(minInterval != NULL) { e->torrentMan->minInterval = minInterval->toInt(); logger->debug("CUID#%d - Min interval:%d", cuid, e->torrentMan->minInterval); } if(e->torrentMan->minInterval > e->torrentMan->interval) { e->torrentMan->minInterval = e->torrentMan->interval; } Data* complete = (Data*)response->get("complete"); if(complete != NULL) { e->torrentMan->complete = complete->toInt(); logger->debug("CUID#%d - Complete:%d", cuid, e->torrentMan->complete); } Data* incomplete = (Data*)response->get("incomplete"); if(incomplete != NULL) { e->torrentMan->incomplete = incomplete->toInt(); logger->debug("CUID#%d - Incomplete:%d", cuid, e->torrentMan->incomplete); } const MetaEntry* peersEntry = response->get("peers"); if(!e->torrentMan->isHalt() && e->torrentMan->connections < MIN_PEERS && peersEntry) { DelegatingPeerListProcessor proc(e->torrentMan->pieceLength, e->torrentMan->getTotalLength()); Peers peers = proc.extractPeer(peersEntry); e->torrentMan->addPeer(peers); while(e->torrentMan->isPeerAvailable() && e->torrentMan->connections < MIN_PEERS) { PeerHandle peer = e->torrentMan->getPeer(); int newCuid = e->torrentMan->getNewCuid(); peer->cuid = newCuid; PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e); e->commands.push_back(command); logger->debug("CUID#%d - Adding new command CUID#%d", cuid, newCuid); } } if(!peersEntry) { logger->info("CUID#%d - No peer list received.", cuid); } if(e->torrentMan->req->getTrackerEvent() == Request::STARTED) { e->torrentMan->req->setTrackerEvent(Request::AUTO); } } catch(Exception* err) { logger->error("CUID#%d - Error occurred while processing tracker response.", cuid, err); delete err; } if(trackerResponse != NULL) { delete [] trackerResponse; } e->torrentMan->trackers = 0; e->segmentMan->init(); if(e->torrentMan->isHalt()) { return true; } else { return prepareForRetry(); } }