From 93968c4fa525d44bf83fb221874a8b8febee3905 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 20 Nov 2009 15:42:25 +0000 Subject: [PATCH] 2009-11-21 Tatsuhiro Tsujikawa Initial support of Extension for Peers to Send Metadata Files(BEP9). Currently aria2 only serves metadata and cannot get metadata from swarm. * src/BtConstants.h * src/DefaultBtInteractive.cc * src/DefaultExtensionMessageFactory.cc * src/DefaultExtensionMessageFactory.h * src/ExtensionMessage.h * src/ExtensionMessageRegistry.h * src/HandshakeExtensionMessage.cc * src/HandshakeExtensionMessage.h * src/Makefile.am * src/PeerConnection.h * src/PeerInteractionCommand.cc * src/UTMetadataDataExtensionMessage.cc * src/UTMetadataDataExtensionMessage.h * src/UTMetadataExtensionMessage.cc * src/UTMetadataExtensionMessage.h * src/UTMetadataRejectExtensionMessage.cc * src/UTMetadataRejectExtensionMessage.h * src/UTMetadataRequestExtensionMessage.cc * src/UTMetadataRequestExtensionMessage.h * src/bittorrent_helper.cc * src/bittorrent_helper.h * test/BittorrentHelperTest.cc * test/DefaultExtensionMessageFactoryTest.cc * test/HandshakeExtensionMessageTest.cc * test/Makefile.am * test/UTMetadataDataExtensionMessageTest.cc * test/UTMetadataRejectExtensionMessageTest.cc * test/UTMetadataRequestExtensionMessageTest.cc --- ChangeLog | 34 ++++ src/BtConstants.h | 2 + src/DefaultBtInteractive.cc | 5 +- src/DefaultExtensionMessageFactory.cc | 78 ++++++++ src/DefaultExtensionMessageFactory.h | 24 +++ src/ExtensionMessage.h | 4 +- src/ExtensionMessageRegistry.h | 2 + src/HandshakeExtensionMessage.cc | 22 ++- src/HandshakeExtensionMessage.h | 22 ++- src/Makefile.am | 5 + src/Makefile.in | 24 ++- src/PeerConnection.h | 6 +- src/PeerInteractionCommand.cc | 5 + src/UTMetadataDataExtensionMessage.cc | 77 ++++++++ src/UTMetadataDataExtensionMessage.h | 79 ++++++++ src/UTMetadataExtensionMessage.cc | 46 +++++ src/UTMetadataExtensionMessage.h | 75 +++++++ src/UTMetadataRejectExtensionMessage.cc | 66 +++++++ src/UTMetadataRejectExtensionMessage.h | 55 ++++++ src/UTMetadataRequestExtensionMessage.cc | 101 ++++++++++ src/UTMetadataRequestExtensionMessage.h | 88 +++++++++ src/bittorrent_helper.cc | 6 + src/bittorrent_helper.h | 4 + test/BittorrentHelperTest.cc | 23 ++- test/DefaultExtensionMessageFactoryTest.cc | 86 ++++++-- test/HandshakeExtensionMessageTest.cc | 36 +++- test/Makefile.am | 3 + test/Makefile.in | 15 +- test/UTMetadataDataExtensionMessageTest.cc | 60 ++++++ test/UTMetadataRejectExtensionMessageTest.cc | 55 ++++++ test/UTMetadataRequestExtensionMessageTest.cc | 186 ++++++++++++++++++ 31 files changed, 1262 insertions(+), 32 deletions(-) create mode 100644 src/UTMetadataDataExtensionMessage.cc create mode 100644 src/UTMetadataDataExtensionMessage.h create mode 100644 src/UTMetadataExtensionMessage.cc create mode 100644 src/UTMetadataExtensionMessage.h create mode 100644 src/UTMetadataRejectExtensionMessage.cc create mode 100644 src/UTMetadataRejectExtensionMessage.h create mode 100644 src/UTMetadataRequestExtensionMessage.cc create mode 100644 src/UTMetadataRequestExtensionMessage.h create mode 100644 test/UTMetadataDataExtensionMessageTest.cc create mode 100644 test/UTMetadataRejectExtensionMessageTest.cc create mode 100644 test/UTMetadataRequestExtensionMessageTest.cc diff --git a/ChangeLog b/ChangeLog index fc997f87..bcd54661 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2009-11-21 Tatsuhiro Tsujikawa + + Initial support of Extension for Peers to Send Metadata + Files(BEP9). Currently aria2 only serves metadata and cannot get + metadata from swarm. + * src/BtConstants.h + * src/DefaultBtInteractive.cc + * src/DefaultExtensionMessageFactory.cc + * src/DefaultExtensionMessageFactory.h + * src/ExtensionMessage.h + * src/ExtensionMessageRegistry.h + * src/HandshakeExtensionMessage.cc + * src/HandshakeExtensionMessage.h + * src/Makefile.am + * src/PeerConnection.h + * src/PeerInteractionCommand.cc + * src/UTMetadataDataExtensionMessage.cc + * src/UTMetadataDataExtensionMessage.h + * src/UTMetadataExtensionMessage.cc + * src/UTMetadataExtensionMessage.h + * src/UTMetadataRejectExtensionMessage.cc + * src/UTMetadataRejectExtensionMessage.h + * src/UTMetadataRequestExtensionMessage.cc + * src/UTMetadataRequestExtensionMessage.h + * src/bittorrent_helper.cc + * src/bittorrent_helper.h + * test/BittorrentHelperTest.cc + * test/DefaultExtensionMessageFactoryTest.cc + * test/HandshakeExtensionMessageTest.cc + * test/Makefile.am + * test/UTMetadataDataExtensionMessageTest.cc + * test/UTMetadataRejectExtensionMessageTest.cc + * test/UTMetadataRequestExtensionMessageTest.cc + 2009-11-21 Tatsuhiro Tsujikawa Cancel segment in prepareForRetry() because there is a chance that diff --git a/src/BtConstants.h b/src/BtConstants.h index 4108755a..e9c40dcc 100644 --- a/src/BtConstants.h +++ b/src/BtConstants.h @@ -58,4 +58,6 @@ typedef std::map Extensions; // Upper Bound of the number of outstanding request #define UB_MAX_OUTSTANDING_REQUEST 24 +#define METADATA_PIECE_SIZE (16*1024) + #endif // _D_BT_CONSTANTS_ diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc index 16cbf4d3..3dd62096 100644 --- a/src/DefaultBtInteractive.cc +++ b/src/DefaultBtInteractive.cc @@ -167,7 +167,10 @@ void DefaultBtInteractive::addHandshakeExtendedMessageToQueue() m->setClientVersion(CLIENT_ARIA2); m->setTCPPort(_btRuntime->getListenPort()); m->setExtensions(_extensionMessageRegistry->getExtensions()); - + const BDE& attrs = _downloadContext->getAttribute(bittorrent::BITTORRENT); + if(attrs.containsKey(bittorrent::METADATA)) { + m->setMetadataSize(attrs[bittorrent::METADATA_SIZE].i()); + } SharedHandle msg = messageFactory->createBtExtendedMessage(m); dispatcher->addMessageToQueue(msg); } diff --git a/src/DefaultExtensionMessageFactory.cc b/src/DefaultExtensionMessageFactory.cc index f28680a4..4dad47e4 100644 --- a/src/DefaultExtensionMessageFactory.cc +++ b/src/DefaultExtensionMessageFactory.cc @@ -42,6 +42,14 @@ #include "StringFormat.h" #include "PeerStorage.h" #include "ExtensionMessageRegistry.h" +#include "DownloadContext.h" +#include "BtMessageDispatcher.h" +#include "BtMessageFactory.h" +#include "UTMetadataRequestExtensionMessage.h" +#include "UTMetadataDataExtensionMessage.h" +#include "UTMetadataRejectExtensionMessage.h" +#include "message.h" +#include "bencode.h" namespace aria2 { @@ -65,6 +73,7 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t // handshake HandshakeExtensionMessageHandle m = HandshakeExtensionMessage::create(data, length); m->setPeer(_peer); + m->setDownloadContext(_dctx); return m; } else { std::string extensionName = _registry->getExtensionName(extensionMessageID); @@ -79,6 +88,75 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t UTPexExtensionMessage::create(data, length); m->setPeerStorage(_peerStorage); return m; + } else if(extensionName == "ut_metadata") { + if(length == 0) { + throw DL_ABORT_EX(StringFormat(MSG_TOO_SMALL_PAYLOAD_SIZE, + "ut_metadata", length).str()); + } + std::string listdata; + listdata += 'l'; + listdata += std::string(&data[1], &data[length]); + listdata += 'e'; + + const BDE& list = bencode::decode(listdata); + if(!list.isList() || list.empty()) { + throw DL_ABORT_EX("Bad ut_metadata"); + } + const BDE& dict = list[0]; + if(!dict.isDict()) { + throw DL_ABORT_EX("Bad ut_metadata: dictionary not found"); + } + const BDE& msgType = dict["msg_type"]; + if(!msgType.isInteger()) { + throw DL_ABORT_EX("Bad ut_metadata: msg_type not found"); + } + const BDE& index = dict["piece"]; + if(!index.isInteger()) { + throw DL_ABORT_EX("Bad ut_metadata: piece not found"); + } + switch(msgType.i()) { + case 0: { + SharedHandle m + (new UTMetadataRequestExtensionMessage(extensionMessageID)); + m->setIndex(index.i()); + m->setDownloadContext(_dctx); + m->setPeer(_peer); + m->setBtMessageFactory(_messageFactory); + m->setBtMessageDispatcher(_dispatcher); + return m; + } + case 1: { + if(list.size() != 2) { + throw DL_ABORT_EX("Bad ut_metadata data: data not found"); + } + const BDE& pieceData = list[1]; + if(!pieceData.isString()) { + throw DL_ABORT_EX("Bad ut_metadata data: data is not string"); + } + const BDE& totalSize = dict["total_size"]; + if(!totalSize.isInteger()) { + throw DL_ABORT_EX("Bad ut_metadata data: total_size not found"); + } + SharedHandle m + (new UTMetadataDataExtensionMessage(extensionMessageID)); + m->setIndex(index.i()); + m->setTotalSize(totalSize.i()); + m->setData(pieceData.s()); + // set tracker + // set piecestorage + return m; + } + case 2: { + SharedHandle m + (new UTMetadataRejectExtensionMessage(extensionMessageID)); + m->setIndex(index.i()); + // set tracker if disconnecing peer on receive. + return m; + } + default: + throw DL_ABORT_EX(StringFormat("Bad ut_metadata: unknown msg_type=%u", + msgType.i()).str()); + } } else { throw DL_ABORT_EX (StringFormat("Unsupported extension message received. extensionMessageID=%u, extensionName=%s", diff --git a/src/DefaultExtensionMessageFactory.h b/src/DefaultExtensionMessageFactory.h index dfc1c0ec..319528f6 100644 --- a/src/DefaultExtensionMessageFactory.h +++ b/src/DefaultExtensionMessageFactory.h @@ -43,6 +43,9 @@ class PeerStorage; class Peer; class Logger; class ExtensionMessageRegistry; +class DownloadContext; +class BtMessageFactory; +class BtMessageDispatcher; class DefaultExtensionMessageFactory:public ExtensionMessageFactory { private: @@ -52,6 +55,12 @@ private: SharedHandle _registry; + SharedHandle _dctx; + + WeakHandle _messageFactory; + + WeakHandle _dispatcher; + Logger* _logger; public: @@ -75,6 +84,21 @@ public: { _registry = registry; } + + void setDownloadContext(const SharedHandle& dctx) + { + _dctx = dctx; + } + + void setBtMessageFactory(const WeakHandle& factory) + { + _messageFactory = factory; + } + + void setBtMessageDispatcher(const WeakHandle& disp) + { + _dispatcher = disp; + } }; typedef SharedHandle DefaultExtensionMessageFactoryHandle; diff --git a/src/ExtensionMessage.h b/src/ExtensionMessage.h index 44902f0b..7d996380 100644 --- a/src/ExtensionMessage.h +++ b/src/ExtensionMessage.h @@ -36,9 +36,11 @@ #define _D_EXTENSION_MESSAGE_H_ #include "common.h" -#include "SharedHandle.h" + #include +#include "SharedHandle.h" + namespace aria2 { class ExtensionMessage { public: diff --git a/src/ExtensionMessageRegistry.h b/src/ExtensionMessageRegistry.h index d79c8e4b..e79a6619 100644 --- a/src/ExtensionMessageRegistry.h +++ b/src/ExtensionMessageRegistry.h @@ -51,6 +51,8 @@ public: ExtensionMessageRegistry() { _extensions["ut_pex"] = 8; + // http://www.bittorrent.org/beps/bep_0009.html + _extensions["ut_metadata"] = 9; } const Extensions& getExtensions() const diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index 5ce2bd7f..a0c04c3a 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * 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 @@ -41,6 +41,8 @@ #include "message.h" #include "StringFormat.h" #include "bencode.h" +#include "DownloadContext.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -48,6 +50,7 @@ const std::string HandshakeExtensionMessage::EXTENSION_NAME = "handshake"; HandshakeExtensionMessage::HandshakeExtensionMessage(): _tcpPort(0), + _metadataSize(0), _logger(LogFactory::getInstance()) {} HandshakeExtensionMessage::~HandshakeExtensionMessage() {} @@ -68,6 +71,9 @@ std::string HandshakeExtensionMessage::getBencodedData() extDict[vt.first] = vt.second; } dict["m"] = extDict; + if(_metadataSize) { + dict["metadata_size"] = _metadataSize; + } return bencode::encode(dict); } @@ -80,6 +86,9 @@ std::string HandshakeExtensionMessage::toString() const if(_tcpPort > 0) { strappend(s, ", tcpPort=", util::uitos(_tcpPort)); } + if(_metadataSize) { + strappend(s, ", metadataSize=", util::uitos(_metadataSize)); + } for(std::map::const_iterator itr = _extensions.begin(); itr != _extensions.end(); ++itr) { const std::map::value_type& vt = *itr; @@ -99,6 +108,12 @@ void HandshakeExtensionMessage::doReceivedAction() const std::map::value_type& vt = *itr; _peer->setExtension(vt.first, vt.second); } + if(_metadataSize > 0) { + BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT); + if(!attrs.containsKey(bittorrent::METADATA_SIZE)) { + attrs[bittorrent::METADATA_SIZE] = _metadataSize; + } + } } void HandshakeExtensionMessage::setPeer(const PeerHandle& peer) @@ -148,6 +163,11 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length) } } } + const BDE& metadataSize = dict["metadata_size"]; + // Only accept metadata smaller than 1MiB + if(metadataSize.isInteger() && metadataSize.i() <= 1024*1024) { + msg->_metadataSize = metadataSize.i(); + } return msg; } diff --git a/src/HandshakeExtensionMessage.h b/src/HandshakeExtensionMessage.h index 3c9c7dd9..73386883 100644 --- a/src/HandshakeExtensionMessage.h +++ b/src/HandshakeExtensionMessage.h @@ -2,7 +2,7 @@ /* * aria2 - The high speed download utility * - * Copyright (C) 2006 Tatsuhiro Tsujikawa + * 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 @@ -46,6 +46,7 @@ namespace aria2 { class Peer; class Logger; class HandshakeExtensionMessage; +class DownloadContext; typedef SharedHandle HandshakeExtensionMessageHandle; class HandshakeExtensionMessage:public ExtensionMessage { @@ -54,8 +55,12 @@ private: uint16_t _tcpPort; + size_t _metadataSize; + std::map _extensions; + SharedHandle _dctx; + SharedHandle _peer; Logger* _logger; @@ -103,6 +108,21 @@ public: return _tcpPort; } + size_t getMetadataSize() + { + return _metadataSize; + } + + void setMetadataSize(size_t size) + { + _metadataSize = size; + } + + void setDownloadContext(const SharedHandle& dctx) + { + _dctx = dctx; + } + void setExtension(const std::string& name, uint8_t id) { _extensions[name] = id; diff --git a/src/Makefile.am b/src/Makefile.am index a3ea139e..1cfe5221 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -346,6 +346,11 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\ DefaultExtensionMessageFactory.cc DefaultExtensionMessageFactory.h\ HandshakeExtensionMessage.cc HandshakeExtensionMessage.h\ UTPexExtensionMessage.cc UTPexExtensionMessage.h\ + UTMetadataExtensionMessage.cc UTMetadataExtensionMessage.h\ + UTMetadataRequestExtensionMessage.cc\ + UTMetadataRequestExtensionMessage.h\ + UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\ + UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\ DHTNode.cc DHTNode.h\ DHTBucket.cc DHTBucket.h\ DHTRoutingTable.cc DHTRoutingTable.h\ diff --git a/src/Makefile.in b/src/Makefile.in index d21dacc6..1bb60b99 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -145,6 +145,11 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactory.cc DefaultExtensionMessageFactory.h\ @ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessage.cc HandshakeExtensionMessage.h\ @ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessage.cc UTPexExtensionMessage.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataExtensionMessage.cc UTMetadataExtensionMessage.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.cc\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.cc UTMetadataRejectExtensionMessage.h\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.cc UTMetadataDataExtensionMessage.h\ @ENABLE_BITTORRENT_TRUE@ DHTNode.cc DHTNode.h\ @ENABLE_BITTORRENT_TRUE@ DHTBucket.cc DHTBucket.h\ @ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.cc DHTRoutingTable.h\ @@ -489,8 +494,15 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ ExtensionMessageFactory.h DefaultExtensionMessageFactory.cc \ DefaultExtensionMessageFactory.h HandshakeExtensionMessage.cc \ HandshakeExtensionMessage.h UTPexExtensionMessage.cc \ - UTPexExtensionMessage.h DHTNode.cc DHTNode.h DHTBucket.cc \ - DHTBucket.h DHTRoutingTable.cc DHTRoutingTable.h \ + UTPexExtensionMessage.h UTMetadataExtensionMessage.cc \ + UTMetadataExtensionMessage.h \ + UTMetadataRequestExtensionMessage.cc \ + UTMetadataRequestExtensionMessage.h \ + UTMetadataRejectExtensionMessage.cc \ + UTMetadataRejectExtensionMessage.h \ + UTMetadataDataExtensionMessage.cc \ + UTMetadataDataExtensionMessage.h DHTNode.cc DHTNode.h \ + DHTBucket.cc DHTBucket.h DHTRoutingTable.cc DHTRoutingTable.h \ DHTMessageEntry.cc DHTMessageEntry.h DHTMessageDispatcher.h \ DHTMessageDispatcherImpl.cc DHTMessageDispatcherImpl.h \ DHTMessageReceiver.cc DHTMessageReceiver.h \ @@ -644,6 +656,10 @@ am__objects_6 = @ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactory.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataExtensionMessage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessage.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTNode.$(OBJEXT) DHTBucket.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTRoutingTable.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTMessageEntry.$(OBJEXT) \ @@ -1511,6 +1527,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransferStat.Po@am__quote@ @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)/UTMetadataRejectExtensionMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestExtensionMessage.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/PeerConnection.h b/src/PeerConnection.h index 2e01ba5b..18ae037c 100644 --- a/src/PeerConnection.h +++ b/src/PeerConnection.h @@ -47,9 +47,9 @@ class SocketCore; class ARC4Encryptor; class ARC4Decryptor; -// we assume maximum length of incoming message is "piece" message with 16KB -// data. Messages beyond that size are dropped. -#define MAX_PAYLOAD_LEN (9+16*1024) +// The maximum length of payload. Messages beyond that length are +// dropped. +#define MAX_PAYLOAD_LEN (16*1024+128) class PeerConnection { private: diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc index 3fe2035f..7507be30 100644 --- a/src/PeerInteractionCommand.cc +++ b/src/PeerInteractionCommand.cc @@ -109,6 +109,8 @@ PeerInteractionCommand::PeerInteractionCommand SharedHandle extensionMessageFactory (new DefaultExtensionMessageFactory(peer, exMsgRegistry)); extensionMessageFactory->setPeerStorage(peerStorage); + extensionMessageFactory->setDownloadContext + (_requestGroup->getDownloadContext()); SharedHandle factory(new DefaultBtMessageFactory()); factory->setCuid(cuid); @@ -189,6 +191,9 @@ PeerInteractionCommand::PeerInteractionCommand factory->setBtRequestFactory(reqFactory); factory->setPeerConnection(peerConnection); + extensionMessageFactory->setBtMessageDispatcher(dispatcher); + extensionMessageFactory->setBtMessageFactory(factory); + peer->allocateSessionResource (_requestGroup->getDownloadContext()->getPieceLength(), _requestGroup->getDownloadContext()->getTotalLength()); diff --git a/src/UTMetadataDataExtensionMessage.cc b/src/UTMetadataDataExtensionMessage.cc new file mode 100644 index 00000000..7f80a608 --- /dev/null +++ b/src/UTMetadataDataExtensionMessage.cc @@ -0,0 +1,77 @@ +/* */ +#include "UTMetadataDataExtensionMessage.h" +#include "BDE.h" +#include "bencode.h" +#include "util.h" +#include "a2functional.h" + +namespace aria2 { + +UTMetadataDataExtensionMessage::UTMetadataDataExtensionMessage +(uint8_t extensionMessageID):UTMetadataExtensionMessage(extensionMessageID) {} + +std::string UTMetadataDataExtensionMessage::getBencodedData() +{ + BDE list = BDE::list(); + + BDE dict = BDE::dict(); + dict["msg_type"] = 1; + dict["piece"] = _index; + dict["total_size"] = _totalSize; + + BDE data = _data; + + list << dict; + list << data; + + std::string encodedList = bencode::encode(list); + // Remove first 'l' and last 'e' and return. + return std::string(encodedList.begin()+1, encodedList.end()-1); +} + +std::string UTMetadataDataExtensionMessage::toString() const +{ + return strconcat("ut_metadata data piece=", util::uitos(_index)); +} + +void UTMetadataDataExtensionMessage::doReceivedAction() +{ + // Update tracker + + // Write to pieceStorage +} + +} // namespace aria2 diff --git a/src/UTMetadataDataExtensionMessage.h b/src/UTMetadataDataExtensionMessage.h new file mode 100644 index 00000000..d2d6aa39 --- /dev/null +++ b/src/UTMetadataDataExtensionMessage.h @@ -0,0 +1,79 @@ +/* */ +#ifndef _D_UT_METADATA_DATA_EXTENSION_MESSAGE_H_ +#define _D_UT_METADATA_DATA_EXTENSION_MESSAGE_H_ + +#include "UTMetadataExtensionMessage.h" + +namespace aria2 { + +class UTMetadataDataExtensionMessage:public UTMetadataExtensionMessage { +private: + size_t _totalSize; + + std::string _data; +public: + UTMetadataDataExtensionMessage(uint8_t extensionMessageID); + + virtual std::string getBencodedData(); + + virtual std::string toString() const; + + virtual void doReceivedAction(); + + void setTotalSize(size_t totalSize) + { + _totalSize = totalSize; + } + + size_t getTotalSize() const + { + return _totalSize; + } + + void setData(const std::string& data) + { + _data = data; + } + + const std::string& getData() const + { + return _data; + } +}; + +} // namespace aria2 + +#endif // _D_UT_METADATA_DATA_EXTENSION_MESSAGE_H_ diff --git a/src/UTMetadataExtensionMessage.cc b/src/UTMetadataExtensionMessage.cc new file mode 100644 index 00000000..2842fb5f --- /dev/null +++ b/src/UTMetadataExtensionMessage.cc @@ -0,0 +1,46 @@ +/* */ +#include "UTMetadataExtensionMessage.h" + +namespace aria2 { + +const std::string UTMetadataExtensionMessage::EXTENSION_NAME = "ut_metadata"; + +UTMetadataExtensionMessage::UTMetadataExtensionMessage +(uint8_t extensionMessageID): + _extensionMessageID(extensionMessageID), + _index(0) {} + +} // namespace aria2 diff --git a/src/UTMetadataExtensionMessage.h b/src/UTMetadataExtensionMessage.h new file mode 100644 index 00000000..0a890ac0 --- /dev/null +++ b/src/UTMetadataExtensionMessage.h @@ -0,0 +1,75 @@ +/* */ +#ifndef _D_UT_METADATA_EXTENSION_MESSAGE_H_ +#define _D_UT_METADATA_EXTENSION_MESSAGE_H_ + +#include "ExtensionMessage.h" + +namespace aria2 { + +class UTMetadataExtensionMessage:public ExtensionMessage { +protected: + uint8_t _extensionMessageID; + + size_t _index; +public: + UTMetadataExtensionMessage(uint8_t extensionMessageID); + + virtual uint8_t getExtensionMessageID() + { + return _extensionMessageID; + } + + virtual const std::string& getExtensionName() const + { + return EXTENSION_NAME; + } + + static const std::string EXTENSION_NAME; + + void setIndex(size_t index) + { + _index = index; + } + + size_t getIndex() + { + return _index; + } +}; + +} // namespace aria2 + +#endif // _D_UT_METADATA_EXTENSION_MESSAGE_H_ diff --git a/src/UTMetadataRejectExtensionMessage.cc b/src/UTMetadataRejectExtensionMessage.cc new file mode 100644 index 00000000..243d1302 --- /dev/null +++ b/src/UTMetadataRejectExtensionMessage.cc @@ -0,0 +1,66 @@ +/* */ +#include "UTMetadataRejectExtensionMessage.h" +#include "BDE.h" +#include "a2functional.h" +#include "util.h" +#include "bencode.h" + +namespace aria2 { + +UTMetadataRejectExtensionMessage::UTMetadataRejectExtensionMessage +(uint8_t extensionMessageID): + UTMetadataExtensionMessage(extensionMessageID) {} + +std::string UTMetadataRejectExtensionMessage::getBencodedData() +{ + BDE dict = BDE::dict(); + dict["msg_type"] = 2; + dict["piece"] = _index; + return bencode::encode(dict); +} + +std::string UTMetadataRejectExtensionMessage::toString() const +{ + return strconcat("ut_metadata reject piece=", util::uitos(_index)); +} + +void UTMetadataRejectExtensionMessage::doReceivedAction() +{ + // TODO Remove outstanding metadata request from tracker. + // OR drop connection. +} + +} // namespace aria2 diff --git a/src/UTMetadataRejectExtensionMessage.h b/src/UTMetadataRejectExtensionMessage.h new file mode 100644 index 00000000..7ce47f03 --- /dev/null +++ b/src/UTMetadataRejectExtensionMessage.h @@ -0,0 +1,55 @@ +/* */ +#ifndef _D_UT_METADATA_REJECT_EXTENSION_MESSAGE_H_ +#define _D_UT_METADATA_REJECT_EXTENSION_MESSAGE_H_ + +#include "UTMetadataExtensionMessage.h" + +namespace aria2 { + +class UTMetadataRejectExtensionMessage:public UTMetadataExtensionMessage { +public: + UTMetadataRejectExtensionMessage(uint8_t extensionMessageID); + + virtual std::string getBencodedData(); + + virtual std::string toString() const; + + virtual void doReceivedAction(); +}; + +} // namespace aria2 + +#endif // _D_UT_METADATA_REJECT_EXTENSION_MESSAGE_H_ diff --git a/src/UTMetadataRequestExtensionMessage.cc b/src/UTMetadataRequestExtensionMessage.cc new file mode 100644 index 00000000..92de8fae --- /dev/null +++ b/src/UTMetadataRequestExtensionMessage.cc @@ -0,0 +1,101 @@ +/* */ +#include "UTMetadataRequestExtensionMessage.h" +#include "BDE.h" +#include "bencode.h" +#include "util.h" +#include "a2functional.h" +#include "bittorrent_helper.h" +#include "DlAbortEx.h" +#include "StringFormat.h" +#include "BtMessageFactory.h" +#include "BtMessageDispatcher.h" +#include "Peer.h" +#include "UTMetadataRejectExtensionMessage.h" +#include "UTMetadataDataExtensionMessage.h" +#include "BtConstants.h" +#include "DownloadContext.h" +#include "BtMessage.h" + +namespace aria2 { + +UTMetadataRequestExtensionMessage::UTMetadataRequestExtensionMessage +(uint8_t extensionMessageID):UTMetadataExtensionMessage(extensionMessageID) {} + +std::string UTMetadataRequestExtensionMessage::getBencodedData() +{ + BDE dict = BDE::dict(); + dict["msg_type"] = 0; + dict["piece"] = _index; + return bencode::encode(dict); +} + +std::string UTMetadataRequestExtensionMessage::toString() const +{ + return strconcat("ut_metadata request piece=", util::uitos(_index)); +} + +void UTMetadataRequestExtensionMessage::doReceivedAction() +{ + const BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT); + uint8_t id = _peer->getExtensionMessageID("ut_metadata"); + if(!attrs.containsKey(bittorrent::METADATA)) { + SharedHandle m + (new UTMetadataRejectExtensionMessage(id)); + m->setIndex(_index); + SharedHandle msg = _messageFactory->createBtExtendedMessage(m); + _dispatcher->addMessageToQueue(msg); + }else if(_index*METADATA_PIECE_SIZE < + (size_t)attrs[bittorrent::METADATA_SIZE].i()){ + SharedHandle m + (new UTMetadataDataExtensionMessage(id)); + m->setIndex(_index); + m->setTotalSize(attrs[bittorrent::METADATA_SIZE].i()); + const BDE& metadata = attrs[bittorrent::METADATA]; + std::string::const_iterator begin = + metadata.s().begin()+_index*METADATA_PIECE_SIZE; + std::string::const_iterator end = + (_index+1)*METADATA_PIECE_SIZE <= metadata.s().size()? + metadata.s().begin()+(_index+1)*METADATA_PIECE_SIZE:metadata.s().end(); + m->setData(std::string(begin, end)); + SharedHandle msg = _messageFactory->createBtExtendedMessage(m); + _dispatcher->addMessageToQueue(msg); + } else { + throw DL_ABORT_EX + (StringFormat("Metadata piece index is too big. piece=%d", _index).str()); + } +} + +} // namespace aria2 diff --git a/src/UTMetadataRequestExtensionMessage.h b/src/UTMetadataRequestExtensionMessage.h new file mode 100644 index 00000000..682af99d --- /dev/null +++ b/src/UTMetadataRequestExtensionMessage.h @@ -0,0 +1,88 @@ +/* */ +#ifndef _D_UT_METADATA_REQUEST_EXTENSION_MESSAGE_H_ +#define _D_UT_METADATA_REQUEST_EXTENSION_MESSAGE_H_ + +#include "UTMetadataExtensionMessage.h" + +namespace aria2 { + +class DownloadContext; +class BtMessageDispatcher; +class BtMessageFactory; +class Peer; + +class UTMetadataRequestExtensionMessage:public UTMetadataExtensionMessage { +private: + SharedHandle _dctx; + + SharedHandle _peer; + + WeakHandle _dispatcher; + + WeakHandle _messageFactory; +public: + UTMetadataRequestExtensionMessage(uint8_t extensionMessageID); + + virtual std::string getBencodedData(); + + virtual std::string toString() const; + + virtual void doReceivedAction(); + + void setDownloadContext(const SharedHandle& dctx) + { + _dctx = dctx; + } + + void setBtMessageDispatcher(const WeakHandle& disp) + { + _dispatcher = disp; + } + + void setBtMessageFactory(const WeakHandle& factory) + { + _messageFactory = factory; + } + + void setPeer(const SharedHandle& peer) + { + _peer = peer; + } +}; + +} // namespace aria2 + +#endif // _D_UT_METADATA_REQUEST_EXTENSION_MESSAGE_H_ diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 68ebb915..0fa05cc4 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -125,6 +125,10 @@ const std::string MULTI("multi"); const std::string SINGLE("single"); +const std::string METADATA_SIZE("metadataSize"); + +const std::string METADATA("metadata"); + static void extractPieceHash(const SharedHandle& ctx, const std::string& hashData, size_t hashLength, @@ -364,6 +368,8 @@ static void processRootDictionary encodedInfoDict.data(), encodedInfoDict.size()); torrent[INFO_HASH] = std::string(&infoHash[0], &infoHash[INFO_HASH_LENGTH]); + torrent[METADATA] = encodedInfoDict; + torrent[METADATA_SIZE] = encodedInfoDict.size(); // calculate the number of pieces const BDE& piecesData = infoDict[C_PIECES]; diff --git a/src/bittorrent_helper.h b/src/bittorrent_helper.h index bc9c8fe9..bf1269a3 100644 --- a/src/bittorrent_helper.h +++ b/src/bittorrent_helper.h @@ -84,6 +84,10 @@ extern const std::string MULTI; extern const std::string BITTORRENT; +extern const std::string METADATA_SIZE; + +extern const std::string METADATA; + void load(const std::string& torrentFile, const SharedHandle& ctx, const std::string& overrideName = ""); diff --git a/test/BittorrentHelperTest.cc b/test/BittorrentHelperTest.cc index 246a98d0..756ed2de 100644 --- a/test/BittorrentHelperTest.cc +++ b/test/BittorrentHelperTest.cc @@ -14,6 +14,8 @@ #include "array_fun.h" #include "messageDigest.h" #include "a2netcompat.h" +#include "bencode.h" +#include "TestUtil.h" namespace aria2 { @@ -52,9 +54,10 @@ class BittorrentHelperTest:public CppUnit::TestFixture { CPPUNIT_TEST(testSetFileFilter_single); CPPUNIT_TEST(testSetFileFilter_multi); CPPUNIT_TEST(testUTF8Torrent); - CPPUNIT_TEST(testMetaData); + CPPUNIT_TEST(testEtc); CPPUNIT_TEST(testCreatecompact); CPPUNIT_TEST(testCheckBitfield); + CPPUNIT_TEST(testMetadata); CPPUNIT_TEST_SUITE_END(); public: void setUp() { @@ -90,9 +93,10 @@ public: void testSetFileFilter_single(); void testSetFileFilter_multi(); void testUTF8Torrent(); - void testMetaData(); + void testEtc(); void testCreatecompact(); void testCheckBitfield(); + void testMetadata(); }; @@ -634,7 +638,7 @@ void BittorrentHelperTest::testUTF8Torrent() dctx->getAttribute(BITTORRENT)[COMMENT].s()); } -void BittorrentHelperTest::testMetaData() +void BittorrentHelperTest::testEtc() { SharedHandle dctx(new DownloadContext()); load("test.torrent", dctx); @@ -678,6 +682,19 @@ void BittorrentHelperTest::testCheckBitfield() } } +void BittorrentHelperTest::testMetadata() { + SharedHandle dctx(new DownloadContext()); + load("test.torrent", dctx); + std::string torrentData = readFile("test.torrent"); + BDE tr = bencode::decode(torrentData); + BDE infoDic = tr["info"]; + std::string metadata = bencode::encode(infoDic); + const BDE& attrs = dctx->getAttribute(bittorrent::BITTORRENT); + CPPUNIT_ASSERT(metadata == attrs[bittorrent::METADATA].s()); + CPPUNIT_ASSERT_EQUAL(metadata.size(), + (size_t)attrs[bittorrent::METADATA_SIZE].i()); +} + } // namespace bittorrent } // namespace aria2 diff --git a/test/DefaultExtensionMessageFactoryTest.cc b/test/DefaultExtensionMessageFactoryTest.cc index 23b71fcc..878bdb06 100644 --- a/test/DefaultExtensionMessageFactoryTest.cc +++ b/test/DefaultExtensionMessageFactoryTest.cc @@ -12,6 +12,15 @@ #include "Exception.h" #include "FileEntry.h" #include "ExtensionMessageRegistry.h" +#include "DownloadContext.h" +#include "MockBtMessageDispatcher.h" +#include "MockBtMessageFactory.h" +#include "DownloadContext.h" +#include "BtHandshakeMessage.h" +#include "StringFormat.h" +#include "UTMetadataRequestExtensionMessage.h" +#include "UTMetadataDataExtensionMessage.h" +#include "UTMetadataRejectExtensionMessage.h" namespace aria2 { @@ -21,12 +30,18 @@ class DefaultExtensionMessageFactoryTest:public CppUnit::TestFixture { CPPUNIT_TEST(testCreateMessage_unknown); CPPUNIT_TEST(testCreateMessage_Handshake); CPPUNIT_TEST(testCreateMessage_UTPex); + CPPUNIT_TEST(testCreateMessage_UTMetadataRequest); + CPPUNIT_TEST(testCreateMessage_UTMetadataData); + CPPUNIT_TEST(testCreateMessage_UTMetadataReject); CPPUNIT_TEST_SUITE_END(); private: SharedHandle _peerStorage; SharedHandle _peer; SharedHandle _factory; SharedHandle _registry; + SharedHandle _dispatcher; + SharedHandle _messageFactory; + SharedHandle _dctx; public: void setUp() { @@ -38,15 +53,41 @@ public: _registry.reset(new ExtensionMessageRegistry()); + _dispatcher.reset(new MockBtMessageDispatcher()); + + _messageFactory.reset(new MockBtMessageFactory()); + + _dctx.reset(new DownloadContext()); + _factory.reset(new DefaultExtensionMessageFactory()); _factory->setPeerStorage(_peerStorage); _factory->setPeer(_peer); _factory->setExtensionMessageRegistry(_registry); + _factory->setBtMessageDispatcher(_dispatcher); + _factory->setBtMessageFactory(_messageFactory); + _factory->setDownloadContext(_dctx); + } + + std::string getExtensionMessageID(const std::string& name) + { + char id[1] = { _registry->getExtensionMessageID(name) }; + return std::string(&id[0], &id[1]); + } + + template + SharedHandle createMessage(const std::string& data) + { + return dynamic_pointer_cast + (_factory->createMessage + (reinterpret_cast(data.c_str()), data.size())); } void testCreateMessage_unknown(); void testCreateMessage_Handshake(); void testCreateMessage_UTPex(); + void testCreateMessage_UTMetadataRequest(); + void testCreateMessage_UTMetadataData(); + void testCreateMessage_UTMetadataReject(); }; @@ -74,10 +115,8 @@ void DefaultExtensionMessageFactoryTest::testCreateMessage_Handshake() char id[1] = { 0 }; std::string data = std::string(&id[0], &id[1])+"d1:v5:aria2e"; - SharedHandle m - (dynamic_pointer_cast - (_factory->createMessage - (reinterpret_cast(data.c_str()), data.size()))); + SharedHandle m = + createMessage(data); CPPUNIT_ASSERT_EQUAL(std::string("aria2"), m->getClientVersion()); } @@ -92,20 +131,45 @@ void DefaultExtensionMessageFactoryTest::testCreateMessage_UTPex() bittorrent::createcompact(c3, "192.168.0.2", 6882); bittorrent::createcompact(c4, "10.1.1.3",10000); - char id[1] = { _registry->getExtensionMessageID("ut_pex") }; - - std::string data = std::string(&id[0], &id[1])+"d5:added12:"+ + std::string data = getExtensionMessageID("ut_pex")+"d5:added12:"+ std::string(&c1[0], &c1[6])+std::string(&c2[0], &c2[6])+ "7:added.f2:207:dropped12:"+ std::string(&c3[0], &c3[6])+std::string(&c4[0], &c4[6])+ "e"; - SharedHandle m - (dynamic_pointer_cast - (_factory->createMessage - (reinterpret_cast(data.c_str()), data.size()))); + SharedHandle m = + createMessage(data); CPPUNIT_ASSERT_EQUAL(_registry->getExtensionMessageID("ut_pex"), m->getExtensionMessageID()); } +void DefaultExtensionMessageFactoryTest::testCreateMessage_UTMetadataRequest() +{ + std::string data = getExtensionMessageID("ut_metadata")+ + "d8:msg_typei0e5:piecei1ee"; + SharedHandle m = + createMessage(data); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->getIndex()); +} + +void DefaultExtensionMessageFactoryTest::testCreateMessage_UTMetadataData() +{ + std::string data = getExtensionMessageID("ut_metadata")+ + "d8:msg_typei1e5:piecei1e10:total_sizei300ee10:0000000000"; + SharedHandle m = + createMessage(data); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->getIndex()); + CPPUNIT_ASSERT_EQUAL((size_t)300, m->getTotalSize()); + CPPUNIT_ASSERT_EQUAL(std::string(10, '0'), m->getData()); +} + +void DefaultExtensionMessageFactoryTest::testCreateMessage_UTMetadataReject() +{ + std::string data = getExtensionMessageID("ut_metadata")+ + "d8:msg_typei2e5:piecei1ee"; + SharedHandle m = + createMessage(data); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->getIndex()); +} + } // namespace aria2 diff --git a/test/HandshakeExtensionMessageTest.cc b/test/HandshakeExtensionMessageTest.cc index b05154d9..b8ceb4dc 100644 --- a/test/HandshakeExtensionMessageTest.cc +++ b/test/HandshakeExtensionMessageTest.cc @@ -7,6 +7,8 @@ #include "Peer.h" #include "Exception.h" #include "FileEntry.h" +#include "DownloadContext.h" +#include "bittorrent_helper.h" namespace aria2 { @@ -57,11 +59,18 @@ void HandshakeExtensionMessageTest::testGetBencodedData() msg.setTCPPort(6889); msg.setExtension("ut_pex", 1); msg.setExtension("a2_dht", 2); - CPPUNIT_ASSERT_EQUAL(std::string("d" - "1:md6:a2_dhti2e6:ut_pexi1ee" - "1:pi6889e" - "1:v5:aria2" - "e"), msg.getBencodedData()); + msg.setMetadataSize(1024); + CPPUNIT_ASSERT_EQUAL + (std::string("d" + "1:md6:a2_dhti2e6:ut_pexi1ee" + "13:metadata_sizei1024e" + "1:pi6889e" + "1:v5:aria2" + "e"), msg.getBencodedData()); + + msg.setMetadataSize(0); + CPPUNIT_ASSERT + (msg.getBencodedData().find("metadata_size") == std::string::npos); } void HandshakeExtensionMessageTest::testToString() @@ -71,11 +80,18 @@ void HandshakeExtensionMessageTest::testToString() msg.setTCPPort(6889); msg.setExtension("ut_pex", 1); msg.setExtension("a2_dht", 2); - CPPUNIT_ASSERT_EQUAL(std::string("handshake client=aria2, tcpPort=6889, a2_dht=2, ut_pex=1"), msg.toString()); + msg.setMetadataSize(1024); + CPPUNIT_ASSERT_EQUAL + (std::string("handshake client=aria2, tcpPort=6889, metadataSize=1024," + " a2_dht=2, ut_pex=1"), msg.toString()); } void HandshakeExtensionMessageTest::testDoReceivedAction() { + SharedHandle ctx(new DownloadContext()); + BDE attrs = BDE::dict(); + ctx->setAttribute(bittorrent::BITTORRENT, attrs); + SharedHandle peer(new Peer("192.168.0.1", 0)); peer->allocateSessionResource(1024, 1024*1024); HandshakeExtensionMessage msg; @@ -83,25 +99,29 @@ void HandshakeExtensionMessageTest::testDoReceivedAction() msg.setTCPPort(6889); msg.setExtension("ut_pex", 1); msg.setExtension("a2_dht", 2); + msg.setMetadataSize(1024); msg.setPeer(peer); + msg.setDownloadContext(ctx); msg.doReceivedAction(); CPPUNIT_ASSERT_EQUAL((uint16_t)6889, peer->port); CPPUNIT_ASSERT_EQUAL((uint8_t)1, peer->getExtensionMessageID("ut_pex")); CPPUNIT_ASSERT_EQUAL((uint8_t)2, peer->getExtensionMessageID("a2_dht")); + CPPUNIT_ASSERT_EQUAL((int64_t)1024, attrs[bittorrent::METADATA_SIZE].i()); } void HandshakeExtensionMessageTest::testCreate() { - std::string in = "0d1:pi6881e1:v5:aria21:md6:ut_pexi1eee"; + std::string in = + "0d1:pi6881e1:v5:aria21:md6:ut_pexi1ee13:metadata_sizei1024ee"; SharedHandle m = HandshakeExtensionMessage::create(reinterpret_cast(in.c_str()), in.size()); CPPUNIT_ASSERT_EQUAL(std::string("aria2"), m->getClientVersion()); CPPUNIT_ASSERT_EQUAL((uint16_t)6881, m->getTCPPort()); CPPUNIT_ASSERT_EQUAL((uint8_t)1, m->getExtensionMessageID("ut_pex")); - + CPPUNIT_ASSERT_EQUAL((size_t)1024, m->getMetadataSize()); try { // bad payload format std::string in = "011:hello world"; diff --git a/test/Makefile.am b/test/Makefile.am index e5d222f1..9198d007 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -136,6 +136,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\ BtExtendedMessageTest.cc\ HandshakeExtensionMessageTest.cc\ UTPexExtensionMessageTest.cc\ + UTMetadataRequestExtensionMessageTest.cc\ + UTMetadataDataExtensionMessageTest.cc\ + UTMetadataRejectExtensionMessageTest.cc\ DefaultBtMessageFactoryTest.cc\ DefaultExtensionMessageFactoryTest.cc\ DHTNodeTest.cc\ diff --git a/test/Makefile.in b/test/Makefile.in index c66893d5..c8559c7e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -86,6 +86,9 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_BITTORRENT_TRUE@ BtExtendedMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessageTest.cc\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessageTest.cc\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessageTest.cc\ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.cc\ @ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.cc\ @ENABLE_BITTORRENT_TRUE@ DHTNodeTest.cc\ @@ -224,7 +227,11 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ BtRegistryTest.cc BtDependencyTest.cc \ BtPostDownloadHandlerTest.cc TimeSeedCriteriaTest.cc \ BtExtendedMessageTest.cc HandshakeExtensionMessageTest.cc \ - UTPexExtensionMessageTest.cc DefaultBtMessageFactoryTest.cc \ + UTPexExtensionMessageTest.cc \ + UTMetadataRequestExtensionMessageTest.cc \ + UTMetadataDataExtensionMessageTest.cc \ + UTMetadataRejectExtensionMessageTest.cc \ + DefaultBtMessageFactoryTest.cc \ DefaultExtensionMessageFactoryTest.cc DHTNodeTest.cc \ DHTBucketTest.cc DHTRoutingTableTest.cc \ DHTMessageTrackerEntryTest.cc DHTMessageTrackerTest.cc \ @@ -296,6 +303,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ @ENABLE_BITTORRENT_TRUE@ BtExtendedMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessageTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRequestExtensionMessageTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataDataExtensionMessageTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ UTMetadataRejectExtensionMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DHTNodeTest.$(OBJEXT) \ @@ -840,6 +850,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestUtil.Po@am__quote@ @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)/UTMetadataRejectExtensionMessageTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestExtensionMessageTest.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/UTMetadataDataExtensionMessageTest.cc b/test/UTMetadataDataExtensionMessageTest.cc new file mode 100644 index 00000000..463aa3a1 --- /dev/null +++ b/test/UTMetadataDataExtensionMessageTest.cc @@ -0,0 +1,60 @@ +#include "UTMetadataDataExtensionMessage.h" + +#include + +#include + +#include "BtConstants.h" + +namespace aria2 { + +class UTMetadataDataExtensionMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(UTMetadataDataExtensionMessageTest); + CPPUNIT_TEST(testGetExtensionMessageID); + CPPUNIT_TEST(testGetBencodedData); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testDoReceivedAction); + CPPUNIT_TEST_SUITE_END(); +public: + void testGetExtensionMessageID(); + void testGetBencodedData(); + void testToString(); + void testDoReceivedAction(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(UTMetadataDataExtensionMessageTest); + +void UTMetadataDataExtensionMessageTest::testGetExtensionMessageID() +{ + UTMetadataDataExtensionMessage msg(1); + CPPUNIT_ASSERT_EQUAL((uint8_t)1, msg.getExtensionMessageID()); +} + +void UTMetadataDataExtensionMessageTest::testGetBencodedData() +{ + std::string data(METADATA_PIECE_SIZE, '0'); + + UTMetadataDataExtensionMessage msg(1); + msg.setIndex(1); + msg.setTotalSize(data.size()); + msg.setData(data); + CPPUNIT_ASSERT_EQUAL + (std::string("d8:msg_typei1e5:piecei1e10:total_sizei16384ee16384:")+data, + msg.getBencodedData()); +} + +void UTMetadataDataExtensionMessageTest::testToString() +{ + UTMetadataDataExtensionMessage msg(1); + msg.setIndex(100); + CPPUNIT_ASSERT_EQUAL(std::string("ut_metadata data piece=100"), + msg.toString()); +} + +void UTMetadataDataExtensionMessageTest::testDoReceivedAction() +{ +} + +} // namespace aria2 diff --git a/test/UTMetadataRejectExtensionMessageTest.cc b/test/UTMetadataRejectExtensionMessageTest.cc new file mode 100644 index 00000000..831ccdf5 --- /dev/null +++ b/test/UTMetadataRejectExtensionMessageTest.cc @@ -0,0 +1,55 @@ +#include "UTMetadataRejectExtensionMessage.h" + +#include + +#include + +#include "BtConstants.h" + +namespace aria2 { + +class UTMetadataRejectExtensionMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(UTMetadataRejectExtensionMessageTest); + CPPUNIT_TEST(testGetExtensionMessageID); + CPPUNIT_TEST(testGetBencodedReject); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testDoReceivedAction); + CPPUNIT_TEST_SUITE_END(); +public: + void testGetExtensionMessageID(); + void testGetBencodedReject(); + void testToString(); + void testDoReceivedAction(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(UTMetadataRejectExtensionMessageTest); + +void UTMetadataRejectExtensionMessageTest::testGetExtensionMessageID() +{ + UTMetadataRejectExtensionMessage msg(1); + CPPUNIT_ASSERT_EQUAL((uint8_t)1, msg.getExtensionMessageID()); +} + +void UTMetadataRejectExtensionMessageTest::testGetBencodedReject() +{ + UTMetadataRejectExtensionMessage msg(1); + msg.setIndex(1); + CPPUNIT_ASSERT_EQUAL + (std::string("d8:msg_typei2e5:piecei1ee"), msg.getBencodedData()); +} + +void UTMetadataRejectExtensionMessageTest::testToString() +{ + UTMetadataRejectExtensionMessage msg(1); + msg.setIndex(100); + CPPUNIT_ASSERT_EQUAL(std::string("ut_metadata reject piece=100"), + msg.toString()); +} + +void UTMetadataRejectExtensionMessageTest::testDoReceivedAction() +{ +} + +} // namespace aria2 diff --git a/test/UTMetadataRequestExtensionMessageTest.cc b/test/UTMetadataRequestExtensionMessageTest.cc new file mode 100644 index 00000000..6d21d776 --- /dev/null +++ b/test/UTMetadataRequestExtensionMessageTest.cc @@ -0,0 +1,186 @@ +#include "UTMetadataRequestExtensionMessage.h" + +#include + +#include + +#include "Peer.h" +#include "DownloadContext.h" +#include "MockBtMessage.h" +#include "MockBtMessageDispatcher.h" +#include "MockBtMessageFactory.h" +#include "bittorrent_helper.h" +#include "BtHandshakeMessage.h" +#include "UTMetadataRejectExtensionMessage.h" +#include "UTMetadataDataExtensionMessage.h" + +namespace aria2 { + +class UTMetadataRequestExtensionMessageTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(UTMetadataRequestExtensionMessageTest); + CPPUNIT_TEST(testGetExtensionMessageID); + CPPUNIT_TEST(testGetExtensionName); + CPPUNIT_TEST(testGetBencodedData); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testDoReceivedAction_reject); + CPPUNIT_TEST(testDoReceivedAction_data); + CPPUNIT_TEST_SUITE_END(); +public: + class MockExtensionMessage:public MockBtMessage { + public: + SharedHandle _m; + + MockExtensionMessage(const SharedHandle& m):_m(m) {} + }; + + class MockBtMessageFactory2:public MockBtMessageFactory { + public: + virtual SharedHandle + createBtExtendedMessage(const SharedHandle& extmsg) + { + return SharedHandle(new MockExtensionMessage(extmsg)); + } + }; + + SharedHandle _dctx; + SharedHandle _messageFactory; + SharedHandle _dispatcher; + SharedHandle _peer; + + void setUp() + { + _messageFactory.reset(new MockBtMessageFactory2()); + _dispatcher.reset(new MockBtMessageDispatcher()); + _dctx.reset(new DownloadContext()); + BDE attrs = BDE::dict(); + _dctx->setAttribute(bittorrent::BITTORRENT, attrs); + _peer.reset(new Peer("host", 6880)); + _peer->allocateSessionResource(0, 0); + _peer->setExtension("ut_metadata", 1); + } + + template + SharedHandle getFirstDispatchedMessage() + { + SharedHandle wrapmsg = + dynamic_pointer_cast + (_dispatcher->messageQueue.front()); + + SharedHandle msg = dynamic_pointer_cast(wrapmsg->_m); + return msg; + } + + void testGetExtensionMessageID(); + void testGetExtensionName(); + void testGetBencodedData(); + void testToString(); + void testDoReceivedAction_reject(); + void testDoReceivedAction_data(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(UTMetadataRequestExtensionMessageTest); + +void UTMetadataRequestExtensionMessageTest::testGetExtensionMessageID() +{ + UTMetadataRequestExtensionMessage msg(1); + CPPUNIT_ASSERT_EQUAL((uint8_t)1, msg.getExtensionMessageID()); +} + +void UTMetadataRequestExtensionMessageTest::testGetExtensionName() +{ + UTMetadataRequestExtensionMessage msg(1); + CPPUNIT_ASSERT_EQUAL(std::string("ut_metadata"), msg.getExtensionName()); +} + +void UTMetadataRequestExtensionMessageTest::testGetBencodedData() +{ + UTMetadataRequestExtensionMessage msg(1); + msg.setIndex(99); + CPPUNIT_ASSERT_EQUAL + (std::string("d8:msg_typei0e5:piecei99ee"), msg.getBencodedData()); +} + +void UTMetadataRequestExtensionMessageTest::testToString() +{ + UTMetadataRequestExtensionMessage msg(1); + msg.setIndex(100); + CPPUNIT_ASSERT_EQUAL(std::string("ut_metadata request piece=100"), + msg.toString()); +} + +void UTMetadataRequestExtensionMessageTest::testDoReceivedAction_reject() +{ + UTMetadataRequestExtensionMessage msg(1); + msg.setIndex(10); + msg.setDownloadContext(_dctx); + msg.setPeer(_peer); + msg.setBtMessageFactory(_messageFactory); + msg.setBtMessageDispatcher(_dispatcher); + msg.doReceivedAction(); + + SharedHandle m = + getFirstDispatchedMessage(); + + CPPUNIT_ASSERT(!m.isNull()); + CPPUNIT_ASSERT_EQUAL((size_t)10, m->getIndex()); + CPPUNIT_ASSERT_EQUAL((uint8_t)1, m->getExtensionMessageID()); +} + +void UTMetadataRequestExtensionMessageTest::testDoReceivedAction_data() +{ + UTMetadataRequestExtensionMessage msg(1); + msg.setIndex(1); + msg.setDownloadContext(_dctx); + msg.setPeer(_peer); + msg.setBtMessageFactory(_messageFactory); + msg.setBtMessageDispatcher(_dispatcher); + + size_t metadataSize = METADATA_PIECE_SIZE*2; + BDE& attrs = _dctx->getAttribute(bittorrent::BITTORRENT); + std::string first(METADATA_PIECE_SIZE, '0'); + std::string second(METADATA_PIECE_SIZE, '1'); + attrs[bittorrent::METADATA] = first+second; + attrs[bittorrent::METADATA_SIZE] = metadataSize; + + msg.doReceivedAction(); + + SharedHandle m = + getFirstDispatchedMessage(); + + CPPUNIT_ASSERT(!m.isNull()); + CPPUNIT_ASSERT_EQUAL((size_t)1, m->getIndex()); + CPPUNIT_ASSERT_EQUAL(second, m->getData()); + CPPUNIT_ASSERT_EQUAL(metadataSize, m->getTotalSize()); + CPPUNIT_ASSERT_EQUAL((uint8_t)1, m->getExtensionMessageID()); + + _dispatcher->messageQueue.clear(); + + msg.setIndex(2); + + metadataSize += 100; + std::string third(100, '2'); + attrs[bittorrent::METADATA] = attrs[bittorrent::METADATA].s()+third; + attrs[bittorrent::METADATA_SIZE] = metadataSize; + + msg.doReceivedAction(); + + m = getFirstDispatchedMessage(); + + CPPUNIT_ASSERT(!m.isNull()); + CPPUNIT_ASSERT_EQUAL((size_t)2, m->getIndex()); + CPPUNIT_ASSERT_EQUAL(third, m->getData()); + CPPUNIT_ASSERT_EQUAL(metadataSize, m->getTotalSize()); + + msg.setIndex(3); + + try { + msg.doReceivedAction(); + CPPUNIT_FAIL("exception must be thrown."); + } catch(DlAbortEx& e) { + // success + } +} + +} // namespace aria2