diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2006-04-19 17:24:23 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2006-04-19 17:24:23 +0000 |
| commit | 1457d7f660ee83fca44730b38a3f2af800684f2a (patch) | |
| tree | c753a83e48a664db882d825c2e938a3544ab872b /src/TrackerUpdateCommand.cc | |
| parent | e199bf88986ce441c3383e3c00ce4864a77023b2 (diff) | |
Diffstat (limited to 'src/TrackerUpdateCommand.cc')
| -rw-r--r-- | src/TrackerUpdateCommand.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/TrackerUpdateCommand.cc b/src/TrackerUpdateCommand.cc new file mode 100644 index 00000000..314ac991 --- /dev/null +++ b/src/TrackerUpdateCommand.cc @@ -0,0 +1,175 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#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 <netinet/in.h> + +TrackerUpdateCommand::TrackerUpdateCommand(int cuid, TorrentDownloadEngine*e):Command(cuid), e(e) { + logger = LogFactory::getInstance(); +} + +TrackerUpdateCommand::~TrackerUpdateCommand() {} + +bool TrackerUpdateCommand::prepareForRetry() { + Command* sleepCommand = new SleepCommand(cuid, e, this, 5); + e->commands.push(sleepCommand); + 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->finished()) { + return prepareForRetry(); + } + MetaEntry* entry = NULL; + char* trackerResponse = NULL; + int trackerResponseLength = 0; + try { + try { + trackerResponse = getTrackerResponse(trackerResponseLength); + entry = MetaFileUtil::bdecoding(trackerResponse, + trackerResponseLength); + if(trackerResponse != NULL) { + delete [] trackerResponse; + } + } catch(Exception* e) { + if(trackerResponse != NULL) { + delete [] trackerResponse; + } + throw; + } + Dictionary* response = (Dictionary*)entry; + 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("Tracker ID:%s", e->torrentMan->trackerId.c_str()); + } + Data* interval = (Data*)response->get("interval"); + if(interval != NULL) { + e->torrentMan->interval = interval->toInt(); + logger->debug("interval:%d", e->torrentMan->interval); + } + Data* minInterval = (Data*)response->get("min interval"); + if(minInterval != NULL) { + e->torrentMan->minInterval = minInterval->toInt(); + logger->debug("min interval:%d", 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("complete:%d", e->torrentMan->complete); + } + Data* incomplete = (Data*)response->get("incomplete"); + if(incomplete != NULL) { + e->torrentMan->incomplete = incomplete->toInt(); + logger->debug("incomplete:%d", e->torrentMan->incomplete); + } + Data* peers = (Data*)response->get("peers"); + if(peers != NULL) { + for(int i = 0; i < peers->getLen(); i += 6) { + unsigned int ipaddr1 = (unsigned char)*(peers->getData()+i); + unsigned int ipaddr2 = (unsigned char)*(peers->getData()+i+1); + unsigned int ipaddr3 = (unsigned char)*(peers->getData()+i+2); + unsigned int ipaddr4 = (unsigned char)*(peers->getData()+i+3); + unsigned int port = ntohs(*(unsigned short int*)(peers->getData()+i+4)); + char ipaddr[16]; + + snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", + ipaddr1, ipaddr2, ipaddr3, ipaddr4); + Peer* peer = new Peer(ipaddr, port, e->torrentMan->pieceLength, + e->torrentMan->getTotalLength()); + if(e->torrentMan->addPeer(peer)) { + logger->debug("adding peer %s:%d", peer->ipaddr.c_str(), peer->port); + } else { + delete peer; + } + } + } else { + logger->info("no peer list received."); + } + while(e->torrentMan->isPeerAvailable() && + e->torrentMan->connections < MAX_PEER_UPDATE) { + Peer* peer = e->torrentMan->getPeer(); + int newCuid = e->torrentMan->getNewCuid(); + peer->cuid = newCuid; + PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(newCuid, peer, e); + e->commands.push(command); + logger->debug("adding new command CUID#%d", newCuid); + } + 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(entry != NULL) { + delete entry; + } + e->torrentMan->trackers = 0; + + e->segmentMan->init(); + + return prepareForRetry(); +} + |
