summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-11-23 13:17:48 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-11-23 13:17:48 +0000
commit6e8074c0876fa97e1ba868e5053fc50cd8f487f5 (patch)
tree9cc95e0d2df514dbb9280de586d0451b98a66229
parent95370fc11f82d3f351e3c4e7a5d462d360c2ac65 (diff)
2009-11-23 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added BitTorrent Magnet Link support. Base32 encoded link is not supported yet. Fixed typo in method name in RequestGroup. In metadataGetMode, don't show "Your share ratio was ..." message. * src/DefaultBtInteractive.cc * src/DefaultBtInteractive.h * src/DownloadHandlerFactory.cc * src/DownloadHandlerFactory.h * src/HandshakeExtensionMessage.cc * src/Makefile.am * src/Metalink2RequestGroup.cc * src/PeerInteractionCommand.cc * src/RequestGroup.cc * src/RequestGroup.h * src/UTMetadataPostDownloadHandler.cc * src/UTMetadataPostDownloadHandler.h * src/download_helper.cc * test/HandshakeExtensionMessageTest.cc * test/Makefile.am * test/UTMetadataPostDownloadHandlerTest.cc * test/UTMetadataRejectExtensionMessageTest.cc
-rw-r--r--ChangeLog23
-rw-r--r--src/DefaultBtInteractive.cc86
-rw-r--r--src/DefaultBtInteractive.h23
-rw-r--r--src/DownloadHandlerFactory.cc12
-rw-r--r--src/DownloadHandlerFactory.h31
-rw-r--r--src/HandshakeExtensionMessage.cc12
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.in14
-rw-r--r--src/Metalink2RequestGroup.cc4
-rw-r--r--src/PeerInteractionCommand.cc36
-rw-r--r--src/RequestGroup.cc81
-rw-r--r--src/RequestGroup.h5
-rw-r--r--src/UTMetadataPostDownloadHandler.cc109
-rw-r--r--src/UTMetadataPostDownloadHandler.h61
-rw-r--r--src/download_helper.cc42
-rw-r--r--test/HandshakeExtensionMessageTest.cc1
-rw-r--r--test/Makefile.am3
-rw-r--r--test/Makefile.in12
-rw-r--r--test/UTMetadataPostDownloadHandlerTest.cc111
-rw-r--r--test/UTMetadataRejectExtensionMessageTest.cc9
20 files changed, 619 insertions, 59 deletions
diff --git a/ChangeLog b/ChangeLog
index dd1ac996..284531d5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
2009-11-23 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
+ Added BitTorrent Magnet Link support. Base32 encoded link is not
+ supported yet. Fixed typo in method name in RequestGroup. In
+ metadataGetMode, don't show "Your share ratio was ..." message.
+ * src/DefaultBtInteractive.cc
+ * src/DefaultBtInteractive.h
+ * src/DownloadHandlerFactory.cc
+ * src/DownloadHandlerFactory.h
+ * src/HandshakeExtensionMessage.cc
+ * src/Makefile.am
+ * src/Metalink2RequestGroup.cc
+ * src/PeerInteractionCommand.cc
+ * src/RequestGroup.cc
+ * src/RequestGroup.h
+ * src/UTMetadataPostDownloadHandler.cc
+ * src/UTMetadataPostDownloadHandler.h
+ * src/download_helper.cc
+ * test/HandshakeExtensionMessageTest.cc
+ * test/Makefile.am
+ * test/UTMetadataPostDownloadHandlerTest.cc
+ * test/UTMetadataRejectExtensionMessageTest.cc
+
+2009-11-23 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
+
In metadataGetMode, don't show SEEDING.
* src/ConsoleStatCalc.cc
diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc
index 3dd62096..df70e063 100644
--- a/src/DefaultBtInteractive.cc
+++ b/src/DefaultBtInteractive.cc
@@ -69,6 +69,8 @@
#include "RequestGroup.h"
#include "RequestGroupMan.h"
#include "bittorrent_helper.h"
+#include "UTMetadataRequestFactory.h"
+#include "UTMetadataRequestTracker.h"
namespace aria2 {
@@ -78,6 +80,7 @@ DefaultBtInteractive::DefaultBtInteractive
:
_downloadContext(downloadContext),
peer(peer),
+ _metadataGetMode(false),
logger(LogFactory::getInstance()),
allowedFastSetSize(10),
keepAliveInterval(120),
@@ -146,11 +149,15 @@ void DefaultBtInteractive::doPostHandshakeProcessing() {
if(peer->isExtendedMessagingEnabled()) {
addHandshakeExtendedMessageToQueue();
}
- addBitfieldMessageToQueue();
+ if(!_metadataGetMode) {
+ addBitfieldMessageToQueue();
+ }
if(peer->isDHTEnabled() && _dhtEnabled) {
addPortMessageToQueue();
}
- addAllowedFastMessageToQueue();
+ if(!_metadataGetMode) {
+ addAllowedFastMessageToQueue();
+ }
sendPendingMessage();
}
@@ -365,6 +372,16 @@ void DefaultBtInteractive::addRequests() {
void DefaultBtInteractive::cancelAllPiece() {
btRequestFactory->removeAllTargetPiece();
+ if(_metadataGetMode && _downloadContext->getTotalLength() > 0) {
+ std::vector<size_t> metadataRequests =
+ _utMetadataRequestTracker->getAllTrackedIndex();
+ for(std::vector<size_t>::const_iterator i = metadataRequests.begin();
+ i != metadataRequests.end(); ++i) {
+ logger->debug("Cancel metadata: piece=%lu",
+ static_cast<unsigned long>(*i));
+ _pieceStorage->cancelPiece(_pieceStorage->getPiece(*i));
+ }
+ }
}
void DefaultBtInteractive::sendPendingMessage() {
@@ -439,29 +456,58 @@ void DefaultBtInteractive::addPeerExchangeMessage()
}
void DefaultBtInteractive::doInteractionProcessing() {
- checkActiveInteraction();
+ if(_metadataGetMode) {
+ sendKeepAlive();
+ _numReceivedMessage = receiveMessages();
+ // PieceStorage is re-initialized with metadata_size in
+ // HandshakeExtensionMessage::doReceivedAction().
+ _pieceStorage =
+ _downloadContext->getOwnerRequestGroup()->getPieceStorage();
+
+ if(peer->getExtensionMessageID("ut_metadata") &&
+ _downloadContext->getTotalLength() > 0) {
+ size_t num = _utMetadataRequestTracker->avail();
+ if(num > 0) {
+ std::deque<SharedHandle<BtMessage> > requests;
+ _utMetadataRequestFactory->create(requests, num, _pieceStorage);
+ dispatcher->addMessageToQueue(requests);
+ }
+ if(_perSecCheckPoint.elapsed(1)) {
+ _perSecCheckPoint.reset();
+ // Drop timeout request after queuing message to give a chance
+ // to other connection to request piece.
+ std::vector<size_t> indexes =
+ _utMetadataRequestTracker->removeTimeoutEntry();
+ for(std::vector<size_t>::const_iterator i = indexes.begin();
+ i != indexes.end(); ++i) {
+ _pieceStorage->cancelPiece(_pieceStorage->getPiece(*i));
+ }
+ }
+ }
+ } else {
+ checkActiveInteraction();
- decideChoking();
+ decideChoking();
- detectMessageFlooding();
+ detectMessageFlooding();
- if(_perSecCheckPoint.elapsed(1)) {
- _perSecCheckPoint.reset();
- dispatcher->checkRequestSlotAndDoNecessaryThing();
- }
- checkHave();
+ if(_perSecCheckPoint.elapsed(1)) {
+ _perSecCheckPoint.reset();
+ dispatcher->checkRequestSlotAndDoNecessaryThing();
+ }
+ checkHave();
- sendKeepAlive();
+ sendKeepAlive();
- _numReceivedMessage = receiveMessages();
+ _numReceivedMessage = receiveMessages();
- btRequestFactory->removeCompletedPiece();
+ btRequestFactory->removeCompletedPiece();
- decideInterest();
- if(!_pieceStorage->downloadFinished()) {
- addRequests();
+ decideInterest();
+ if(!_pieceStorage->downloadFinished()) {
+ addRequests();
+ }
}
-
if(peer->getExtensionMessageID("ut_pex") && _utPexEnabled) {
addPeerExchangeMessage();
}
@@ -491,7 +537,11 @@ size_t DefaultBtInteractive::countReceivedMessageInIteration() const
size_t DefaultBtInteractive::countOutstandingRequest()
{
- return dispatcher->countOutstandingRequest();
+ if(_metadataGetMode) {
+ return _utMetadataRequestTracker->count();
+ } else {
+ return dispatcher->countOutstandingRequest();
+ }
}
void DefaultBtInteractive::setBtRuntime
diff --git a/src/DefaultBtInteractive.h b/src/DefaultBtInteractive.h
index 2f5d1b4b..923e5d07 100644
--- a/src/DefaultBtInteractive.h
+++ b/src/DefaultBtInteractive.h
@@ -59,6 +59,8 @@ class ExtensionMessageRegistry;
class DHTNode;
class Logger;
class RequestGroupMan;
+class UTMetadataRequestFactory;
+class UTMetadataRequestTracker;
class FloodingStat {
private:
@@ -114,6 +116,10 @@ private:
SharedHandle<BtMessageFactory> messageFactory;
SharedHandle<ExtensionMessageFactory> _extensionMessageFactory;
SharedHandle<ExtensionMessageRegistry> _extensionMessageRegistry;
+ SharedHandle<UTMetadataRequestFactory> _utMetadataRequestFactory;
+ SharedHandle<UTMetadataRequestTracker> _utMetadataRequestTracker;
+
+ bool _metadataGetMode;
WeakHandle<DHTNode> _localNode;
@@ -230,6 +236,23 @@ public:
}
void setRequestGroupMan(const WeakHandle<RequestGroupMan>& rgman);
+
+ void setUTMetadataRequestTracker
+ (const SharedHandle<UTMetadataRequestTracker>& tracker)
+ {
+ _utMetadataRequestTracker = tracker;
+ }
+
+ void setUTMetadataRequestFactory
+ (const SharedHandle<UTMetadataRequestFactory>& factory)
+ {
+ _utMetadataRequestFactory = factory;
+ }
+
+ void enableMetadataGetMode()
+ {
+ _metadataGetMode = true;
+ }
};
typedef SharedHandle<DefaultBtInteractive> DefaultBtInteractiveHandle;
diff --git a/src/DownloadHandlerFactory.cc b/src/DownloadHandlerFactory.cc
index 15a8cd98..128372a5 100644
--- a/src/DownloadHandlerFactory.cc
+++ b/src/DownloadHandlerFactory.cc
@@ -38,6 +38,7 @@
#include "BtPostDownloadHandler.h"
#include "DownloadHandlerConstants.h"
#include "ContentTypeRequestGroupCriteria.h"
+#include "UTMetadataPostDownloadHandler.h"
namespace aria2 {
@@ -59,6 +60,8 @@ DownloadHandlerFactory::_btPreDownloadHandler;
BtPostDownloadHandlerHandle
DownloadHandlerFactory::_btPostDownloadHandler;
+SharedHandle<UTMetadataPostDownloadHandler>
+DownloadHandlerFactory::_btMetadataPostDownloadHandler;
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
@@ -118,6 +121,15 @@ BtPostDownloadHandlerHandle DownloadHandlerFactory::getBtPostDownloadHandler()
return _btPostDownloadHandler;
}
+SharedHandle<UTMetadataPostDownloadHandler>
+DownloadHandlerFactory::getUTMetadataPostDownloadHandler()
+{
+ if(_btMetadataPostDownloadHandler.isNull()) {
+ _btMetadataPostDownloadHandler.reset(new UTMetadataPostDownloadHandler());
+ }
+ return _btMetadataPostDownloadHandler;
+}
+
#endif // ENABLE_BITTORRENT
} // namespace aria2
diff --git a/src/DownloadHandlerFactory.h b/src/DownloadHandlerFactory.h
index dd3247c0..0b3b7816 100644
--- a/src/DownloadHandlerFactory.h
+++ b/src/DownloadHandlerFactory.h
@@ -46,33 +46,48 @@ class MetalinkPostDownloadHandler;
#endif // ENABLE_METALINK
#ifdef ENABLE_BITTORRENT
class BtPostDownloadHandler;
+class UTMetadataPostDownloadHandler;
#endif // ENABLE_BITTORRENT
class DownloadHandlerFactory
{
private:
#ifdef ENABLE_METALINK
- static SharedHandle<MemoryBufferPreDownloadHandler> _metalinkPreDownloadHandler;
+ static SharedHandle<MemoryBufferPreDownloadHandler>
+ _metalinkPreDownloadHandler;
- static SharedHandle<MetalinkPostDownloadHandler> _metalinkPostDownloadHandler;
+ static SharedHandle<MetalinkPostDownloadHandler>
+ _metalinkPostDownloadHandler;
#endif // ENABLE_METALINK
#ifdef ENABLE_BITTORRENT
- static SharedHandle<MemoryBufferPreDownloadHandler> _btPreDownloadHandler;
+ static SharedHandle<MemoryBufferPreDownloadHandler>
+ _btPreDownloadHandler;
- static SharedHandle<BtPostDownloadHandler> _btPostDownloadHandler;
+ static SharedHandle<BtPostDownloadHandler>
+ _btPostDownloadHandler;
+
+ static SharedHandle<UTMetadataPostDownloadHandler>
+ _btMetadataPostDownloadHandler;
#endif // ENABLE_BITTORRENT
public:
#ifdef ENABLE_METALINK
- static SharedHandle<MemoryBufferPreDownloadHandler> getMetalinkPreDownloadHandler();
+ static SharedHandle<MemoryBufferPreDownloadHandler>
+ getMetalinkPreDownloadHandler();
- static SharedHandle<MetalinkPostDownloadHandler> getMetalinkPostDownloadHandler();
+ static SharedHandle<MetalinkPostDownloadHandler>
+ getMetalinkPostDownloadHandler();
#endif // ENABLE_METALINK
#ifdef ENABLE_BITTORRENT
- static SharedHandle<MemoryBufferPreDownloadHandler> getBtPreDownloadHandler();
+ static SharedHandle<MemoryBufferPreDownloadHandler>
+ getBtPreDownloadHandler();
+
+ static SharedHandle<BtPostDownloadHandler>
+ getBtPostDownloadHandler();
- static SharedHandle<BtPostDownloadHandler> getBtPostDownloadHandler();
+ static SharedHandle<UTMetadataPostDownloadHandler>
+ getUTMetadataPostDownloadHandler();
#endif // ENABLE_BITTORRENT
};
diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc
index fd722e78..74c713be 100644
--- a/src/HandshakeExtensionMessage.cc
+++ b/src/HandshakeExtensionMessage.cc
@@ -110,8 +110,15 @@ void HandshakeExtensionMessage::doReceivedAction()
const std::map<std::string, uint8_t>::value_type& vt = *itr;
_peer->setExtension(vt.first, vt.second);
}
+ BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT);
+ if(!attrs.containsKey(bittorrent::METADATA) &&
+ !_peer->getExtensionMessageID("ut_metadata")) {
+ // TODO In metadataGetMode, if peer dont' support metadata
+ // transfer, should we drop connection? There is a possibility
+ // that peer can still tell us peers using PEX.
+ throw DL_ABORT_EX("Peer doesn't support ut_metadata extension. Goodbye.");
+ }
if(_metadataSize > 0) {
- BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT);
if(attrs.containsKey(bittorrent::METADATA_SIZE)) {
if(_metadataSize != (size_t)attrs[bittorrent::METADATA_SIZE].i()) {
throw DL_ABORT_EX("Wrong metadata_size. Which one is correct!?");
@@ -126,6 +133,9 @@ void HandshakeExtensionMessage::doReceivedAction()
_dctx->getOwnerRequestGroup()->getPieceStorage();
pieceStorage->setEndGamePieceNum(0);
}
+ } else {
+ throw DL_ABORT_EX("Peer didn't provide metadata_size."
+ " It seems that it doesn't have whole metadata.");
}
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 1cfe5221..2f06976e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -351,6 +351,9 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\
UTMetadataRequestExtensionMessage.h\
UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\
UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\
+ UTMetadataRequestTracker.cc UTMetadataRequestTracker.h\
+ UTMetadataRequestFactory.cc UTMetadataRequestFactory.h\
+ UTMetadataPostDownloadHandler.cc UTMetadataPostDownloadHandler.h\
DHTNode.cc DHTNode.h\
DHTBucket.cc DHTBucket.h\
DHTRoutingTable.cc DHTRoutingTable.h\
diff --git a/src/Makefile.in b/src/Makefile.in
index 1bb60b99..eb3a5bcb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -150,6 +150,9 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.h\
@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\
@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTracker.cc UTMetadataRequestTracker.h\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactory.cc UTMetadataRequestFactory.h\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandler.cc UTMetadataPostDownloadHandler.h\
@ENABLE_BITTORRENT_TRUE@ DHTNode.cc DHTNode.h\
@ENABLE_BITTORRENT_TRUE@ DHTBucket.cc DHTBucket.h\
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.cc DHTRoutingTable.h\
@@ -501,7 +504,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
UTMetadataRejectExtensionMessage.cc \
UTMetadataRejectExtensionMessage.h \
UTMetadataDataExtensionMessage.cc \
- UTMetadataDataExtensionMessage.h DHTNode.cc DHTNode.h \
+ UTMetadataDataExtensionMessage.h UTMetadataRequestTracker.cc \
+ UTMetadataRequestTracker.h UTMetadataRequestFactory.cc \
+ UTMetadataRequestFactory.h UTMetadataPostDownloadHandler.cc \
+ UTMetadataPostDownloadHandler.h DHTNode.cc DHTNode.h \
DHTBucket.cc DHTBucket.h DHTRoutingTable.cc DHTRoutingTable.h \
DHTMessageEntry.cc DHTMessageEntry.h DHTMessageDispatcher.h \
DHTMessageDispatcherImpl.cc DHTMessageDispatcherImpl.h \
@@ -660,6 +666,9 @@ am__objects_6 =
@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTracker.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactory.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandler.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTNode.$(OBJEXT) DHTBucket.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTMessageEntry.$(OBJEXT) \
@@ -1529,8 +1538,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/URIResult.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataDataExtensionMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataExtensionMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataPostDownloadHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRejectExtensionMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestExtensionMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestTracker.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnknownLengthPieceStorage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParser.Po@am__quote@
diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc
index 8e74871c..78718341 100644
--- a/src/Metalink2RequestGroup.cc
+++ b/src/Metalink2RequestGroup.cc
@@ -179,8 +179,8 @@ Metalink2RequestGroup::createRequestGroup
//dctx->setDir(_option->get(PREF_DIR));
dctx->getFirstFileEntry()->setUris(uris);
torrentRg->setDownloadContext(dctx);
- torrentRg->clearPreDowloadHandler();
- torrentRg->clearPostDowloadHandler();
+ torrentRg->clearPreDownloadHandler();
+ torrentRg->clearPostDownloadHandler();
// remove "metalink" from Accept Type list to avoid loop in tranparent
// metalink
torrentRg->removeAcceptType(RequestGroup::ACCEPT_METALINK);
diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc
index 7507be30..5cbf025f 100644
--- a/src/PeerInteractionCommand.cc
+++ b/src/PeerInteractionCommand.cc
@@ -71,6 +71,8 @@
#include "RequestGroupMan.h"
#include "ExtensionMessageRegistry.h"
#include "bittorrent_helper.h"
+#include "UTMetadataRequestFactory.h"
+#include "UTMetadataRequestTracker.h"
namespace aria2 {
@@ -103,14 +105,27 @@ PeerInteractionCommand::PeerInteractionCommand
SharedHandle<PeerStorage> peerStorage =
btRegistry->get(torrentAttrs[bittorrent::INFO_HASH].s())._peerStorage;
+ bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA);
+
SharedHandle<ExtensionMessageRegistry> exMsgRegistry
(new ExtensionMessageRegistry());
+ SharedHandle<UTMetadataRequestFactory> utMetadataRequestFactory;
+ SharedHandle<UTMetadataRequestTracker> utMetadataRequestTracker;
+ if(metadataGetMode) {
+ utMetadataRequestFactory.reset(new UTMetadataRequestFactory());
+ utMetadataRequestTracker.reset(new UTMetadataRequestTracker());
+ }
+
SharedHandle<DefaultExtensionMessageFactory> extensionMessageFactory
(new DefaultExtensionMessageFactory(peer, exMsgRegistry));
extensionMessageFactory->setPeerStorage(peerStorage);
extensionMessageFactory->setDownloadContext
(_requestGroup->getDownloadContext());
+ extensionMessageFactory->setUTMetadataRequestTracker
+ (utMetadataRequestTracker);
+ extensionMessageFactory->setBtRuntime(_btRuntime);
+ // PieceStorage will be set later.
SharedHandle<DefaultBtMessageFactory> factory(new DefaultBtMessageFactory());
factory->setCuid(cuid);
@@ -123,6 +138,9 @@ PeerInteractionCommand::PeerInteractionCommand
factory->setRoutingTable(DHTRegistry::_routingTable);
factory->setTaskQueue(DHTRegistry::_taskQueue);
factory->setTaskFactory(DHTRegistry::_taskFactory);
+ if(metadataGetMode) {
+ factory->enableMetadataGetMode();
+ }
PeerConnectionHandle peerConnection;
if(passedPeerConnection.isNull()) {
@@ -174,7 +192,7 @@ PeerInteractionCommand::PeerInteractionCommand
(getOption()->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL));
btInteractive->setRequestGroupMan(e->_requestGroupMan);
btInteractive->setBtMessageFactory(factory);
- if(torrentAttrs[bittorrent::PRIVATE].i() == 0) {
+ if(metadataGetMode || torrentAttrs[bittorrent::PRIVATE].i() == 0) {
if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) {
btInteractive->setUTPexEnabled(true);
}
@@ -184,6 +202,12 @@ PeerInteractionCommand::PeerInteractionCommand
factory->setDHTEnabled(true);
}
}
+ btInteractive->setUTMetadataRequestFactory(utMetadataRequestFactory);
+ btInteractive->setUTMetadataRequestTracker(utMetadataRequestTracker);
+ if(metadataGetMode) {
+ btInteractive->enableMetadataGetMode();
+ }
+
this->btInteractive = btInteractive;
// reverse depends
@@ -194,6 +218,16 @@ PeerInteractionCommand::PeerInteractionCommand
extensionMessageFactory->setBtMessageDispatcher(dispatcher);
extensionMessageFactory->setBtMessageFactory(factory);
+ if(metadataGetMode) {
+ utMetadataRequestFactory->setDownloadContext
+ (_requestGroup->getDownloadContext());
+ utMetadataRequestFactory->setBtMessageDispatcher(dispatcher);
+ utMetadataRequestFactory->setBtMessageFactory(factory);
+ utMetadataRequestFactory->setPeer(peer);
+ utMetadataRequestFactory->setUTMetadataRequestTracker
+ (utMetadataRequestTracker);
+ }
+
peer->allocateSessionResource
(_requestGroup->getDownloadContext()->getPieceLength(),
_requestGroup->getDownloadContext()->getTotalLength());
diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc
index 8317592c..a07bd8ff 100644
--- a/src/RequestGroup.cc
+++ b/src/RequestGroup.cc
@@ -196,14 +196,15 @@ void RequestGroup::closeFile()
}
}
-void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
- DownloadEngine* e)
+void RequestGroup::createInitialCommand
+(std::deque<Command*>& commands, DownloadEngine* e)
{
#ifdef ENABLE_BITTORRENT
{
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
const BDE& torrentAttrs =
_downloadContext->getAttribute(bittorrent::BITTORRENT);
+ bool metadataGetMode = !torrentAttrs.containsKey(bittorrent::METADATA);
if(_option->getAsBool(PREF_DRY_RUN)) {
throw DOWNLOAD_FAILURE_EXCEPTION
("Cancel BitTorrent download in dry-run context.");
@@ -214,35 +215,45 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
throw DOWNLOAD_FAILURE_EXCEPTION
(StringFormat
("InfoHash %s is already registered.",
- util::toHex(torrentAttrs[bittorrent::INFO_HASH].s()).c_str()).str());
+ bittorrent::getInfoHashString(_downloadContext).c_str()).str());
}
-
- if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
- throw DOWNLOAD_FAILURE_EXCEPTION
- (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
- _downloadContext->getBasePath().c_str()).str());
- }
- initPieceStorage();
- if(_downloadContext->getFileEntries().size() > 1) {
- _pieceStorage->setupFileFilter();
+ if(metadataGetMode) {
+ // Use UnknownLengthPieceStorage.
+ initPieceStorage();
+ } else {
+ if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
+ throw DOWNLOAD_FAILURE_EXCEPTION
+ (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
+ _downloadContext->getBasePath().c_str()).str());
+ }
+ initPieceStorage();
+ if(_downloadContext->getFileEntries().size() > 1) {
+ _pieceStorage->setupFileFilter();
+ }
}
- SharedHandle<DefaultBtProgressInfoFile>
- progressInfoFile(new DefaultBtProgressInfoFile(_downloadContext,
- _pieceStorage,
- _option.get()));
+ SharedHandle<DefaultBtProgressInfoFile> progressInfoFile;
+ if(!metadataGetMode) {
+ progressInfoFile.reset(new DefaultBtProgressInfoFile(_downloadContext,
+ _pieceStorage,
+ _option.get()));
+ }
BtRuntimeHandle btRuntime(new BtRuntime());
btRuntime->setMaxPeers(_option->getAsInt(PREF_BT_MAX_PEERS));
_btRuntime = btRuntime;
- progressInfoFile->setBtRuntime(btRuntime);
+ if(!progressInfoFile.isNull()) {
+ progressInfoFile->setBtRuntime(btRuntime);
+ }
SharedHandle<DefaultPeerStorage> peerStorage
(new DefaultPeerStorage(_option.get()));
peerStorage->setBtRuntime(btRuntime);
peerStorage->setPieceStorage(_pieceStorage);
_peerStorage = peerStorage;
- progressInfoFile->setPeerStorage(peerStorage);
+ if(!progressInfoFile.isNull()) {
+ progressInfoFile->setPeerStorage(peerStorage);
+ }
SharedHandle<DefaultBtAnnounce> btAnnounce
(new DefaultBtAnnounce(_downloadContext, _option.get()));
@@ -259,7 +270,21 @@ void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
peerStorage,
btAnnounce,
btRuntime,
- progressInfoFile));
+ (progressInfoFile.isNull()?
+ _progressInfoFile:
+ SharedHandle<BtProgressInfoFile>
+ (progressInfoFile))));
+ if(metadataGetMode) {
+ std::deque<Command*> dhtCommands;
+ DHTSetup().setup(dhtCommands, e, _option.get());
+ e->addCommand(dhtCommands);
+
+ SharedHandle<CheckIntegrityEntry> entry
+ (new BtCheckIntegrityEntry(this));
+ entry->onDownloadIncomplete(commands, e);
+
+ return;
+ }
// Remove the control file if download file doesn't exist
if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
@@ -875,12 +900,12 @@ void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler
_preDownloadHandlers.push_back(handler);
}
-void RequestGroup::clearPostDowloadHandler()
+void RequestGroup::clearPostDownloadHandler()
{
_postDownloadHandlers.clear();
}
-void RequestGroup::clearPreDowloadHandler()
+void RequestGroup::clearPreDownloadHandler()
{
_preDownloadHandlers.clear();
}
@@ -934,11 +959,15 @@ void RequestGroup::reportDownloadFinished()
#ifdef ENABLE_BITTORRENT
if(_downloadContext->hasAttribute(bittorrent::BITTORRENT)) {
TransferStat stat = calculateStat();
- double shareRatio = ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
- _logger->notice(MSG_SHARE_RATIO_REPORT,
- shareRatio,
- util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
- util::abbrevSize(getCompletedLength()).c_str());
+ double shareRatio =
+ ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
+ const BDE& attrs = _downloadContext->getAttribute(bittorrent::BITTORRENT);
+ if(attrs.containsKey(bittorrent::METADATA)) {
+ _logger->notice(MSG_SHARE_RATIO_REPORT,
+ shareRatio,
+ util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
+ util::abbrevSize(getCompletedLength()).c_str());
+ }
}
#endif // ENABLE_BITTORRENT
}
diff --git a/src/RequestGroup.h b/src/RequestGroup.h
index 4f499be1..f390d1ae 100644
--- a/src/RequestGroup.h
+++ b/src/RequestGroup.h
@@ -169,6 +169,7 @@ private:
// returns downloadresultcode::UNKNOWN_ERROR.
downloadresultcode::RESULT downloadResult() const;
public:
+ // The copy of option is stored in RequestGroup object.
RequestGroup(const SharedHandle<Option>& option);
~RequestGroup();
@@ -334,13 +335,13 @@ public:
void addPostDownloadHandler(const SharedHandle<PostDownloadHandler>& handler);
- void clearPostDowloadHandler();
+ void clearPostDownloadHandler();
void preDownloadProcessing();
void addPreDownloadHandler(const SharedHandle<PreDownloadHandler>& handler);
- void clearPreDowloadHandler();
+ void clearPreDownloadHandler();
void processCheckIntegrityEntry(std::deque<Command*>& commands,
const SharedHandle<CheckIntegrityEntry>& entry,
diff --git a/src/UTMetadataPostDownloadHandler.cc b/src/UTMetadataPostDownloadHandler.cc
new file mode 100644
index 00000000..14f8ce6e
--- /dev/null
+++ b/src/UTMetadataPostDownloadHandler.cc
@@ -0,0 +1,109 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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 "UTMetadataPostDownloadHandler.h"
+#include "BDE.h"
+#include "bittorrent_helper.h"
+#include "RequestGroup.h"
+#include "download_helper.h"
+#include "RecoverableException.h"
+#include "A2STR.h"
+#include "DownloadContext.h"
+#include "Logger.h"
+#include "util.h"
+#include "a2functional.h"
+#include "DiskAdaptor.h"
+#include "PieceStorage.h"
+
+namespace aria2 {
+
+bool UTMetadataPostDownloadHandler::Criteria::match
+(const RequestGroup* requestGroup) const
+{
+ SharedHandle<DownloadContext> dctx =
+ requestGroup->getDownloadContext();
+ if(dctx->hasAttribute(bittorrent::BITTORRENT)) {
+ const BDE& attrs = dctx->getAttribute(bittorrent::BITTORRENT);
+ if(!attrs.containsKey(bittorrent::METADATA)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+UTMetadataPostDownloadHandler::UTMetadataPostDownloadHandler()
+{
+ setCriteria(SharedHandle<Criteria>(new Criteria()));
+}
+
+void UTMetadataPostDownloadHandler::getNextRequestGroups
+(std::deque<SharedHandle<RequestGroup> >& groups, RequestGroup* requestGroup)
+{
+ SharedHandle<DownloadContext> dctx = requestGroup->getDownloadContext();
+ const BDE& attrs = dctx->getAttribute(bittorrent::BITTORRENT);
+ std::string torrent =
+ strconcat("d4:info",
+ util::toString(requestGroup->getPieceStorage()->getDiskAdaptor()),
+ "e");
+ try {
+ std::deque<SharedHandle<RequestGroup> > newRgs;
+ createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(),
+ std::deque<std::string>(), torrent);
+ if(attrs.containsKey(bittorrent::ANNOUNCE_LIST)) {
+ for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
+ newRgs.begin(); i != newRgs.end(); ++i) {
+ SharedHandle<DownloadContext> newDctx = (*i)->getDownloadContext();
+ if(!newDctx->hasAttribute(bittorrent::BITTORRENT)) {
+ continue;
+ }
+ BDE& newAttrs = newDctx->getAttribute(bittorrent::BITTORRENT);
+ if(attrs[bittorrent::INFO_HASH].s() !=
+ newAttrs[bittorrent::INFO_HASH].s()) {
+ continue;
+ }
+ if(!newAttrs.containsKey(bittorrent::ANNOUNCE_LIST)) {
+ newAttrs[bittorrent::ANNOUNCE_LIST] =
+ attrs[bittorrent::ANNOUNCE_LIST];
+ }
+ break;
+ }
+ }
+
+ groups.insert(groups.end(), newRgs.begin(), newRgs.end());
+ } catch(RecoverableException& e) {
+ _logger->error("Failed to parse BitTorrent metadata.", e);
+ }
+}
+
+} // namespace aria2
diff --git a/src/UTMetadataPostDownloadHandler.h b/src/UTMetadataPostDownloadHandler.h
new file mode 100644
index 00000000..3e566d32
--- /dev/null
+++ b/src/UTMetadataPostDownloadHandler.h
@@ -0,0 +1,61 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2009 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_UT_METADATA_POST_DOWNLOAD_HANDLER_H_
+#define _D_UT_METADATA_POST_DOWNLOAD_HANDLER_H_
+
+#include "PostDownloadHandler.h"
+#include "RequestGroupCriteria.h"
+
+namespace aria2 {
+
+class UTMetadataPostDownloadHandler:public PostDownloadHandler
+{
+private:
+ class Criteria:public RequestGroupCriteria
+ {
+ public:
+ virtual bool match(const RequestGroup* requestGroup) const;
+ };
+public:
+ UTMetadataPostDownloadHandler();
+
+ virtual void
+ getNextRequestGroups(std::deque<SharedHandle<RequestGroup> >& groups,
+ RequestGroup* requestGroup);
+};
+
+} // namespace aria2
+
+#endif // _D_UT_METADATA_POST_DOWNLOAD_HANDLER_H_
diff --git a/src/download_helper.cc b/src/download_helper.cc
index 900604ac..ee7c5bdf 100644
--- a/src/download_helper.cc
+++ b/src/download_helper.cc
@@ -61,8 +61,11 @@
#include "OptionHandler.h"
#include "ByteArrayDiskWriter.h"
#include "a2functional.h"
+#include "ByteArrayDiskWriterFactory.h"
#ifdef ENABLE_BITTORRENT
# include "bittorrent_helper.h"
+# include "BtConstants.h"
+# include "UTMetadataPostDownloadHandler.h"
#endif // ENABLE_BITTORRENT
namespace aria2 {
@@ -224,6 +227,35 @@ createBtRequestGroup(const std::string& torrentFilePath,
return rg;
}
+static
+SharedHandle<RequestGroup>
+createBtMagnetRequestGroup(const std::string& magnetLink,
+ const SharedHandle<Option>& option,
+ const std::deque<std::string>& auxUris)
+{
+ SharedHandle<RequestGroup> rg(new RequestGroup(option));
+ SharedHandle<DownloadContext> dctx
+ (new DownloadContext(METADATA_PIECE_SIZE, 0,
+ A2STR::NIL));
+ dctx->setDir(A2STR::NIL);
+ // We only know info hash. Total Length is unknown at this moment.
+ dctx->markTotalLengthIsUnknown();
+ rg->setFileAllocationEnabled(false);
+ rg->setPreLocalFileCheckEnabled(false);
+ bittorrent::parseMagnetLink(magnetLink, dctx);
+ dctx->getFirstFileEntry()->setPath
+ (dctx->getAttribute(bittorrent::BITTORRENT)[bittorrent::NAME].s());
+ rg->setDownloadContext(dctx);
+ dctx->setOwnerRequestGroup(rg.get());
+ rg->clearPostDownloadHandler();
+ rg->addPostDownloadHandler
+ (SharedHandle<UTMetadataPostDownloadHandler>
+ (new UTMetadataPostDownloadHandler()));
+ rg->setDiskWriterFactory
+ (SharedHandle<DiskWriterFactory>(new ByteArrayDiskWriterFactory()));
+ return rg;
+}
+
void createRequestGroupForBitTorrent
(std::deque<SharedHandle<RequestGroup> >& result,
const SharedHandle<Option>& option,
@@ -304,6 +336,16 @@ public:
// We simply ignore it.
LogFactory::getInstance()->error(EX_EXCEPTION_CAUGHT, e);
}
+ } else if(_detector.guessTorrentMagnet(uri)) {
+ try {
+ SharedHandle<RequestGroup> group =
+ createBtMagnetRequestGroup(uri, _option, std::deque<std::string>());
+ _requestGroups.push_back(group);
+ } catch(RecoverableException& e) {
+ // error occurred while parsing torrent file.
+ // We simply ignore it.
+ LogFactory::getInstance()->error(EX_EXCEPTION_CAUGHT, e);
+ }
}
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
diff --git a/test/HandshakeExtensionMessageTest.cc b/test/HandshakeExtensionMessageTest.cc
index 03818f6e..69494674 100644
--- a/test/HandshakeExtensionMessageTest.cc
+++ b/test/HandshakeExtensionMessageTest.cc
@@ -108,6 +108,7 @@ void HandshakeExtensionMessageTest::testDoReceivedAction()
msg.setTCPPort(6889);
msg.setExtension("ut_pex", 1);
msg.setExtension("a2_dht", 2);
+ msg.setExtension("ut_metadata", 3);
msg.setMetadataSize(1024);
msg.setPeer(peer);
msg.setDownloadContext(dctx);
diff --git a/test/Makefile.am b/test/Makefile.am
index 9198d007..3485ae5a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -139,6 +139,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
UTMetadataRequestExtensionMessageTest.cc\
UTMetadataDataExtensionMessageTest.cc\
UTMetadataRejectExtensionMessageTest.cc\
+ UTMetadataRequestTrackerTest.cc\
+ UTMetadataRequestFactoryTest.cc\
+ UTMetadataPostDownloadHandlerTest.cc\
DefaultBtMessageFactoryTest.cc\
DefaultExtensionMessageFactoryTest.cc\
DHTNodeTest.cc\
diff --git a/test/Makefile.in b/test/Makefile.in
index c8559c7e..b0659278 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -89,6 +89,9 @@ check_PROGRAMS = $(am__EXEEXT_1)
@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessageTest.cc\
@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessageTest.cc\
@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessageTest.cc\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTrackerTest.cc\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactoryTest.cc\
+@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandlerTest.cc\
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.cc\
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.cc\
@ENABLE_BITTORRENT_TRUE@ DHTNodeTest.cc\
@@ -231,6 +234,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
UTMetadataRequestExtensionMessageTest.cc \
UTMetadataDataExtensionMessageTest.cc \
UTMetadataRejectExtensionMessageTest.cc \
+ UTMetadataRequestTrackerTest.cc \
+ UTMetadataRequestFactoryTest.cc \
+ UTMetadataPostDownloadHandlerTest.cc \
DefaultBtMessageFactoryTest.cc \
DefaultExtensionMessageFactoryTest.cc DHTNodeTest.cc \
DHTBucketTest.cc DHTRoutingTableTest.cc \
@@ -306,6 +312,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessageTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessageTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessageTest.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestTrackerTest.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestFactoryTest.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ UTMetadataPostDownloadHandlerTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTNodeTest.$(OBJEXT) \
@@ -851,8 +860,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataDataExtensionMessageTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataPostDownloadHandlerTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRejectExtensionMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestExtensionMessageTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestFactoryTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestTrackerTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParserTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@
diff --git a/test/UTMetadataPostDownloadHandlerTest.cc b/test/UTMetadataPostDownloadHandlerTest.cc
new file mode 100644
index 00000000..30578005
--- /dev/null
+++ b/test/UTMetadataPostDownloadHandlerTest.cc
@@ -0,0 +1,111 @@
+#include "UTMetadataPostDownloadHandler.h"
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "DownloadContext.h"
+#include "RequestGroup.h"
+#include "Option.h"
+#include "FileEntry.h"
+#include "bittorrent_helper.h"
+#include "A2STR.h"
+#include "ByteArrayDiskWriterFactory.h"
+#include "PieceStorage.h"
+#include "DiskAdaptor.h"
+#include "util.h"
+#include "MessageDigestHelper.h"
+
+namespace aria2 {
+
+class UTMetadataPostDownloadHandlerTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(UTMetadataPostDownloadHandlerTest);
+ CPPUNIT_TEST(testCanHandle);
+ CPPUNIT_TEST(testGetNextRequestGroups);
+ CPPUNIT_TEST_SUITE_END();
+private:
+ SharedHandle<Option> _option;
+ SharedHandle<DownloadContext> _dctx;
+ SharedHandle<RequestGroup> _requestGroup;
+public:
+ void setUp()
+ {
+ _option.reset(new Option());
+ _option->put("HELLO", "WORLD");
+ _dctx.reset(new DownloadContext(0, 0, "something"));
+ _requestGroup.reset(new RequestGroup(_option));
+ _requestGroup->setDownloadContext(_dctx);
+ }
+
+ void testCanHandle();
+ void testGetNextRequestGroups();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( UTMetadataPostDownloadHandlerTest );
+
+void UTMetadataPostDownloadHandlerTest::testCanHandle()
+{
+ UTMetadataPostDownloadHandler handler;
+
+ CPPUNIT_ASSERT(!handler.canHandle(_requestGroup.get()));
+
+ BDE attrs = BDE::dict();
+ _dctx->setAttribute(bittorrent::BITTORRENT, attrs);
+
+ CPPUNIT_ASSERT(handler.canHandle(_requestGroup.get()));
+
+ // Only checks existence of METADATA key
+ attrs[bittorrent::METADATA] = A2STR::NIL;
+
+ CPPUNIT_ASSERT(!handler.canHandle(_requestGroup.get()));
+}
+
+void UTMetadataPostDownloadHandlerTest::testGetNextRequestGroups()
+{
+ std::string metadata =
+ "d6:lengthi384e4:name19:aria2-0.8.2.tar.bz212:piece lengthi128e"
+ "6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCe";
+ unsigned char infoHash[20];
+ MessageDigestHelper::digest
+ (infoHash, sizeof(infoHash), MessageDigestContext::SHA1,
+ reinterpret_cast<const unsigned char*>(metadata.data()), metadata.size());
+ _dctx->getFirstFileEntry()->setLength(metadata.size());
+ BDE attrs = BDE::dict();
+ attrs[bittorrent::INFO_HASH] = std::string(&infoHash[0], &infoHash[20]);
+ BDE announceList = BDE::list();
+ attrs[bittorrent::ANNOUNCE_LIST] = announceList;
+ _dctx->setAttribute(bittorrent::BITTORRENT, attrs);
+ _requestGroup->setDiskWriterFactory
+ (SharedHandle<DiskWriterFactory>(new ByteArrayDiskWriterFactory()));
+ _requestGroup->initPieceStorage();
+ _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData
+ (reinterpret_cast<const unsigned char*>(metadata.data()), metadata.size(),
+ 0);
+
+ UTMetadataPostDownloadHandler handler;
+ std::deque<SharedHandle<RequestGroup> > results;
+ handler.getNextRequestGroups(results, _requestGroup.get());
+
+ CPPUNIT_ASSERT_EQUAL((size_t)1, results.size());
+ SharedHandle<RequestGroup> newRg = results.front();
+ SharedHandle<DownloadContext> newDctx = newRg->getDownloadContext();
+ const BDE& newAttrs = newDctx->getAttribute(bittorrent::BITTORRENT);
+ CPPUNIT_ASSERT_EQUAL(util::toHex(attrs[bittorrent::INFO_HASH].s()),
+ util::toHex(newAttrs[bittorrent::INFO_HASH].s()));
+ CPPUNIT_ASSERT(newAttrs.containsKey(bittorrent::ANNOUNCE_LIST));
+ CPPUNIT_ASSERT_EQUAL(_option->get("Hello"),
+ newRg->getOption()->get("Hello"));
+
+ results.clear();
+
+ // See failure with bad metadata
+ metadata = "d6:lengthi384e4:name19:aria2-0.8.2.tar.bz212:piece lengthi128e";
+ _requestGroup->initPieceStorage();
+ _requestGroup->getPieceStorage()->getDiskAdaptor()->writeData
+ (reinterpret_cast<const unsigned char*>(metadata.data()), metadata.size(),
+ 0);
+ handler.getNextRequestGroups(results, _requestGroup.get());
+ CPPUNIT_ASSERT(results.empty());
+}
+
+} // namespace aria2
diff --git a/test/UTMetadataRejectExtensionMessageTest.cc b/test/UTMetadataRejectExtensionMessageTest.cc
index 831ccdf5..f80b8711 100644
--- a/test/UTMetadataRejectExtensionMessageTest.cc
+++ b/test/UTMetadataRejectExtensionMessageTest.cc
@@ -5,6 +5,7 @@
#include <cppunit/extensions/HelperMacros.h>
#include "BtConstants.h"
+#include "DlAbortEx.h"
namespace aria2 {
@@ -50,6 +51,14 @@ void UTMetadataRejectExtensionMessageTest::testToString()
void UTMetadataRejectExtensionMessageTest::testDoReceivedAction()
{
+ UTMetadataRejectExtensionMessage msg(1);
+ msg.setIndex(0);
+ try {
+ msg.doReceivedAction();
+ CPPUNIT_FAIL("exception must be thrown.");
+ } catch(DlAbortEx& e) {
+ // success
+ }
}
} // namespace aria2