mirror of https://github.com/aria2/aria2
2010-08-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added IPv6 DHT. Added --dht-entry-porint6, --dht-file-path6, --dht-listen-addr6 and --enable-dht6 option. IPv6 DHT is disabled by default. To use IPv6 DHT, you need to use --enable-dht6 and specify a global unicast address to --dht-listen-addr6. IPv6 DHT is highly experimental. * src/BtSetup.cc * src/DHTAutoSaveCommand.cc * src/DHTAutoSaveCommand.h * src/DHTConnectionImpl.cc * src/DHTConnectionImpl.h * src/DHTEntryPointNameResolveCommand.cc * src/DHTFindNodeReplyMessage.cc * src/DHTFindNodeReplyMessage.h * src/DHTGetPeersMessage.cc * src/DHTGetPeersReplyMessage.cc * src/DHTGetPeersReplyMessage.h * src/DHTMessageFactory.h * src/DHTMessageFactoryImpl.cc * src/DHTMessageFactoryImpl.h * src/DHTMessageTracker.cc * src/DHTRegistry.cc * src/DHTRegistry.h * src/DHTRoutingTableDeserializer.cc * src/DHTRoutingTableDeserializer.h * src/DHTRoutingTableSerializer.cc * src/DHTRoutingTableSerializer.h * src/DHTSetup.cc * src/DHTSetup.h * src/FtpConnection.cc * src/LpdMessageReceiver.cc * src/OptionHandlerFactory.cc * src/OptionHandlerImpl.h * src/PeerInteractionCommand.cc * src/RequestGroup.cc * src/SocketCore.cc * src/SocketCore.h * src/bittorrent_helper.cc * src/bittorrent_helper.h * src/prefs.cc * src/prefs.h * src/usage_text.h * test/DHTConnectionImplTest.cc * test/DHTFindNodeReplyMessageTest.cc * test/DHTGetPeersMessageTest.cc * test/DHTGetPeersReplyMessageTest.cc * test/DHTMessageFactoryImplTest.cc * test/DHTRoutingTableDeserializerTest.cc * test/DHTRoutingTableSerializerTest.cc * test/LpdMessageDispatcherTest.cc * test/MockDHTMessageFactory.hpull/1/head
parent
be7012272d
commit
26d6692376
55
ChangeLog
55
ChangeLog
|
@ -1,4 +1,57 @@
|
|||
2010-08-05 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
2010-08-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Added IPv6 DHT. Added --dht-entry-porint6, --dht-file-path6,
|
||||
--dht-listen-addr6 and --enable-dht6 option. IPv6 DHT is disabled
|
||||
by default. To use IPv6 DHT, you need to use --enable-dht6 and
|
||||
specify a global unicast address to --dht-listen-addr6. IPv6 DHT
|
||||
is highly experimental.
|
||||
* src/BtSetup.cc
|
||||
* src/DHTAutoSaveCommand.cc
|
||||
* src/DHTAutoSaveCommand.h
|
||||
* src/DHTConnectionImpl.cc
|
||||
* src/DHTConnectionImpl.h
|
||||
* src/DHTEntryPointNameResolveCommand.cc
|
||||
* src/DHTFindNodeReplyMessage.cc
|
||||
* src/DHTFindNodeReplyMessage.h
|
||||
* src/DHTGetPeersMessage.cc
|
||||
* src/DHTGetPeersReplyMessage.cc
|
||||
* src/DHTGetPeersReplyMessage.h
|
||||
* src/DHTMessageFactory.h
|
||||
* src/DHTMessageFactoryImpl.cc
|
||||
* src/DHTMessageFactoryImpl.h
|
||||
* src/DHTMessageTracker.cc
|
||||
* src/DHTRegistry.cc
|
||||
* src/DHTRegistry.h
|
||||
* src/DHTRoutingTableDeserializer.cc
|
||||
* src/DHTRoutingTableDeserializer.h
|
||||
* src/DHTRoutingTableSerializer.cc
|
||||
* src/DHTRoutingTableSerializer.h
|
||||
* src/DHTSetup.cc
|
||||
* src/DHTSetup.h
|
||||
* src/FtpConnection.cc
|
||||
* src/LpdMessageReceiver.cc
|
||||
* src/OptionHandlerFactory.cc
|
||||
* src/OptionHandlerImpl.h
|
||||
* src/PeerInteractionCommand.cc
|
||||
* src/RequestGroup.cc
|
||||
* src/SocketCore.cc
|
||||
* src/SocketCore.h
|
||||
* src/bittorrent_helper.cc
|
||||
* src/bittorrent_helper.h
|
||||
* src/prefs.cc
|
||||
* src/prefs.h
|
||||
* src/usage_text.h
|
||||
* test/DHTConnectionImplTest.cc
|
||||
* test/DHTFindNodeReplyMessageTest.cc
|
||||
* test/DHTGetPeersMessageTest.cc
|
||||
* test/DHTGetPeersReplyMessageTest.cc
|
||||
* test/DHTMessageFactoryImplTest.cc
|
||||
* test/DHTRoutingTableDeserializerTest.cc
|
||||
* test/DHTRoutingTableSerializerTest.cc
|
||||
* test/LpdMessageDispatcherTest.cc
|
||||
* test/MockDHTMessageFactory.h
|
||||
|
||||
2010-08-07 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Removed AI_V4MAPPED from DEFAULT_AI_FLAGS
|
||||
* src/a2netcompat.h
|
||||
|
|
|
@ -58,6 +58,15 @@
|
|||
#include "DHTPeerAnnounceStorage.h"
|
||||
#include "DHTSetup.h"
|
||||
#include "DHTRegistry.h"
|
||||
#include "DHTNode.h"
|
||||
#include "DHTRoutingTable.h"
|
||||
#include "DHTTaskQueue.h"
|
||||
#include "DHTTaskFactory.h"
|
||||
#include "DHTTokenTracker.h"
|
||||
#include "DHTMessageDispatcher.h"
|
||||
#include "DHTMessageReceiver.h"
|
||||
#include "DHTMessageFactory.h"
|
||||
#include "DHTMessageCallback.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
#include "BtAnnounce.h"
|
||||
#include "BtRuntime.h"
|
||||
|
@ -126,15 +135,25 @@ void BtSetup::setup(std::vector<Command*>& commands,
|
|||
commands.push_back(c);
|
||||
}
|
||||
|
||||
if((metadataGetMode || !torrentAttrs->privateTorrent) &&
|
||||
DHTSetup::initialized()) {
|
||||
DHTGetPeersCommand* command =
|
||||
new DHTGetPeersCommand(e->newCUID(), requestGroup, e);
|
||||
command->setTaskQueue(DHTRegistry::getData().taskQueue);
|
||||
command->setTaskFactory(DHTRegistry::getData().taskFactory);
|
||||
command->setBtRuntime(btRuntime);
|
||||
command->setPeerStorage(peerStorage);
|
||||
commands.push_back(command);
|
||||
if(metadataGetMode || !torrentAttrs->privateTorrent) {
|
||||
if(DHTRegistry::isInitialized()) {
|
||||
DHTGetPeersCommand* command =
|
||||
new DHTGetPeersCommand(e->newCUID(), requestGroup, e);
|
||||
command->setTaskQueue(DHTRegistry::getData().taskQueue);
|
||||
command->setTaskFactory(DHTRegistry::getData().taskFactory);
|
||||
command->setBtRuntime(btRuntime);
|
||||
command->setPeerStorage(peerStorage);
|
||||
commands.push_back(command);
|
||||
}
|
||||
if(DHTRegistry::isInitialized6()) {
|
||||
DHTGetPeersCommand* command =
|
||||
new DHTGetPeersCommand(e->newCUID(), requestGroup, e);
|
||||
command->setTaskQueue(DHTRegistry::getData6().taskQueue);
|
||||
command->setTaskFactory(DHTRegistry::getData6().taskFactory);
|
||||
command->setBtRuntime(btRuntime);
|
||||
command->setPeerStorage(peerStorage);
|
||||
commands.push_back(command);
|
||||
}
|
||||
}
|
||||
if(!metadataGetMode) {
|
||||
SharedHandle<UnionSeedCriteria> unionCri(new UnionSeedCriteria());
|
||||
|
|
|
@ -62,8 +62,9 @@
|
|||
namespace aria2 {
|
||||
|
||||
DHTAutoSaveCommand::DHTAutoSaveCommand
|
||||
(cuid_t cuid, DownloadEngine* e, time_t interval):
|
||||
TimeBasedCommand(cuid, e, interval) {}
|
||||
(cuid_t cuid, DownloadEngine* e, int family, time_t interval):
|
||||
TimeBasedCommand(cuid, e, interval),
|
||||
family_(family) {}
|
||||
|
||||
DHTAutoSaveCommand::~DHTAutoSaveCommand() {}
|
||||
|
||||
|
@ -84,7 +85,8 @@ void DHTAutoSaveCommand::process()
|
|||
void DHTAutoSaveCommand::save()
|
||||
{
|
||||
std::string dhtFile =
|
||||
getDownloadEngine()->getOption()->get(PREF_DHT_FILE_PATH);
|
||||
getDownloadEngine()->getOption()->
|
||||
get(family_ == AF_INET? PREF_DHT_FILE_PATH : PREF_DHT_FILE_PATH6);
|
||||
getLogger()->info("Saving DHT routing table to %s.", dhtFile.c_str());
|
||||
|
||||
std::string tempFile = dhtFile;
|
||||
|
@ -116,7 +118,7 @@ void DHTAutoSaveCommand::save()
|
|||
nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.end());
|
||||
}
|
||||
|
||||
DHTRoutingTableSerializer serializer;
|
||||
DHTRoutingTableSerializer serializer(family_);
|
||||
serializer.setLocalNode(localNode_);
|
||||
serializer.setNodes(nodes);
|
||||
|
||||
|
|
|
@ -46,13 +46,16 @@ class DHTNode;
|
|||
class DHTAutoSaveCommand : public TimeBasedCommand
|
||||
{
|
||||
private:
|
||||
int family_;
|
||||
|
||||
SharedHandle<DHTNode> localNode_;
|
||||
|
||||
SharedHandle<DHTRoutingTable> routingTable_;
|
||||
|
||||
void save();
|
||||
public:
|
||||
DHTAutoSaveCommand(cuid_t cuid, DownloadEngine* e, time_t interval);
|
||||
DHTAutoSaveCommand
|
||||
(cuid_t cuid, DownloadEngine* e, int family, time_t interval);
|
||||
|
||||
virtual ~DHTAutoSaveCommand();
|
||||
|
||||
|
|
|
@ -46,12 +46,15 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
DHTConnectionImpl::DHTConnectionImpl():socket_(new SocketCore(SOCK_DGRAM)),
|
||||
logger_(LogFactory::getInstance()) {}
|
||||
DHTConnectionImpl::DHTConnectionImpl(int family):
|
||||
socket_(new SocketCore(SOCK_DGRAM)),
|
||||
family_(family),
|
||||
logger_(LogFactory::getInstance()) {}
|
||||
|
||||
DHTConnectionImpl::~DHTConnectionImpl() {}
|
||||
|
||||
bool DHTConnectionImpl::bind(uint16_t& port, IntSequence& ports)
|
||||
bool DHTConnectionImpl::bind
|
||||
(uint16_t& port, const std::string& addr, IntSequence& ports)
|
||||
{
|
||||
std::vector<int32_t> randPorts = ports.flush();
|
||||
std::random_shuffle(randPorts.begin(), randPorts.end(),
|
||||
|
@ -63,25 +66,30 @@ bool DHTConnectionImpl::bind(uint16_t& port, IntSequence& ports)
|
|||
continue;
|
||||
}
|
||||
port = (*portItr);
|
||||
if(bind(port)) {
|
||||
if(bind(port, addr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DHTConnectionImpl::bind(uint16_t& port)
|
||||
bool DHTConnectionImpl::bind(uint16_t& port, const std::string& addr)
|
||||
{
|
||||
int ipv = family_ == AF_INET?4:6;
|
||||
try {
|
||||
socket_->bind(port);
|
||||
if(addr.empty()) {
|
||||
socket_->bind(A2STR::NIL, port, family_);
|
||||
} else {
|
||||
socket_->bind(addr, port, family_);
|
||||
}
|
||||
socket_->setNonBlockingMode();
|
||||
std::pair<std::string, uint16_t> svaddr;
|
||||
socket_->getAddrInfo(svaddr);
|
||||
port = svaddr.second;
|
||||
logger_->notice("DHT: listening to port %d", port);
|
||||
logger_->notice("IPv%d DHT: listening to port %d", ipv, port);
|
||||
return true;
|
||||
} catch(RecoverableException& e) {
|
||||
logger_->error("Failed to bind for DHT. port=%u", e, port);
|
||||
logger_->error("Failed to bind for IPv%d DHT. port=%u", e, ipv, port);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,28 +48,33 @@ class DHTConnectionImpl:public DHTConnection {
|
|||
private:
|
||||
SharedHandle<SocketCore> socket_;
|
||||
|
||||
int family_;
|
||||
|
||||
Logger* logger_;
|
||||
public:
|
||||
DHTConnectionImpl();
|
||||
DHTConnectionImpl(int family);
|
||||
|
||||
virtual ~DHTConnectionImpl();
|
||||
|
||||
/**
|
||||
* Binds port. All number in ports are tried.
|
||||
* If successful, the binded port is assigned to port and returns true.
|
||||
* Otherwise return false and port is undefined in this case.
|
||||
* Binds port. All number in ports are tried. If successful, the
|
||||
* binded port is assigned to port and returns true. Otherwise
|
||||
* return false and port is undefined in this case. If non-empty
|
||||
* string addr is given, the socket is associated to the address.
|
||||
*/
|
||||
bool bind(uint16_t& port, IntSequence& ports);
|
||||
bool bind(uint16_t& port, const std::string& addr, IntSequence& ports);
|
||||
|
||||
/**
|
||||
* Binds port. The port number specified by port is used to bind.
|
||||
* If successful, the binded port is assigned to port and returns true.
|
||||
* Otherwise return false and port is undefined in this case.
|
||||
* If successful, the binded port is assigned to port and returns
|
||||
* true. Otherwise return false and port is undefined in this case.
|
||||
* If non-empty string addr is given, the socket is associated to
|
||||
* the address.
|
||||
*
|
||||
* If you want to bind arbitrary port, give 0 as port and if successful,
|
||||
* the binded port is assigned to port.
|
||||
*/
|
||||
bool bind(uint16_t& port);
|
||||
bool bind(uint16_t& port, const std::string& addr);
|
||||
|
||||
virtual ssize_t receiveMessage(unsigned char* data, size_t len,
|
||||
std::string& host, uint16_t& port);
|
||||
|
|
|
@ -96,7 +96,12 @@ bool DHTEntryPointNameResolveCommand::execute()
|
|||
while(!entryPoints_.empty()) {
|
||||
std::string hostname = entryPoints_.front().first;
|
||||
try {
|
||||
if(resolveHostname(hostname, resolver_)) {
|
||||
if(util::isNumericHost(hostname)) {
|
||||
std::pair<std::string, uint16_t> p
|
||||
(hostname, entryPoints_.front().second);
|
||||
resolvedEntryPoints_.push_back(p);
|
||||
addPingTask(p);
|
||||
} else if(resolveHostname(hostname, resolver_)) {
|
||||
hostname = resolver_->getResolvedAddresses().front();
|
||||
std::pair<std::string, uint16_t> p(hostname,
|
||||
entryPoints_.front().second);
|
||||
|
|
|
@ -51,11 +51,15 @@ const std::string DHTFindNodeReplyMessage::FIND_NODE("find_node");
|
|||
|
||||
const std::string DHTFindNodeReplyMessage::NODES("nodes");
|
||||
|
||||
const std::string DHTFindNodeReplyMessage::NODES6("nodes6");
|
||||
|
||||
DHTFindNodeReplyMessage::DHTFindNodeReplyMessage
|
||||
(const SharedHandle<DHTNode>& localNode,
|
||||
(int family,
|
||||
const SharedHandle<DHTNode>& localNode,
|
||||
const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::string& transactionID):
|
||||
DHTResponseMessage(localNode, remoteNode, transactionID) {}
|
||||
DHTResponseMessage(localNode, remoteNode, transactionID),
|
||||
family_(family) {}
|
||||
|
||||
DHTFindNodeReplyMessage::~DHTFindNodeReplyMessage() {}
|
||||
|
||||
|
@ -73,23 +77,27 @@ SharedHandle<Dict> DHTFindNodeReplyMessage::getResponse()
|
|||
{
|
||||
SharedHandle<Dict> aDict = Dict::g();
|
||||
aDict->put(DHTMessage::ID, String::g(getLocalNode()->getID(), DHT_ID_LENGTH));
|
||||
unsigned char buffer[DHTBucket::K*38];
|
||||
const int clen = bittorrent::getCompactLength(family_);
|
||||
const int unit = clen+20;
|
||||
assert(unit <= 38);
|
||||
size_t offset = 0;
|
||||
unsigned char buffer[DHTBucket::K*26];
|
||||
// TODO if closestKNodes_.size() > DHTBucket::K ??
|
||||
size_t k = 0;
|
||||
for(std::vector<SharedHandle<DHTNode> >::const_iterator i =
|
||||
closestKNodes_.begin(), eoi = closestKNodes_.end();
|
||||
i != eoi && offset < DHTBucket::K*26; ++i) {
|
||||
i != eoi && k < DHTBucket::K; ++i) {
|
||||
SharedHandle<DHTNode> node = *i;
|
||||
memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
|
||||
unsigned char compact[COMPACT_LEN_IPV6];
|
||||
int compactlen = bittorrent::packcompact
|
||||
(compact, node->getIPAddress(), node->getPort());
|
||||
if(compactlen == COMPACT_LEN_IPV4) {
|
||||
if(compactlen == clen) {
|
||||
memcpy(buffer+20+offset, compact, compactlen);
|
||||
offset += 26;
|
||||
offset += unit;
|
||||
++k;
|
||||
}
|
||||
}
|
||||
aDict->put(NODES, String::g(buffer, offset));
|
||||
aDict->put(family_ == AF_INET?NODES:NODES6, String::g(buffer, offset));
|
||||
return aDict;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,11 +42,14 @@ namespace aria2 {
|
|||
|
||||
class DHTFindNodeReplyMessage:public DHTResponseMessage {
|
||||
private:
|
||||
int family_;
|
||||
|
||||
std::vector<SharedHandle<DHTNode> > closestKNodes_;
|
||||
protected:
|
||||
virtual std::string toStringOptional() const;
|
||||
public:
|
||||
DHTFindNodeReplyMessage(const SharedHandle<DHTNode>& localNode,
|
||||
DHTFindNodeReplyMessage(int family,
|
||||
const SharedHandle<DHTNode>& localNode,
|
||||
const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::string& transactionID);
|
||||
|
||||
|
@ -71,6 +74,8 @@ public:
|
|||
static const std::string FIND_NODE;
|
||||
|
||||
static const std::string NODES;
|
||||
|
||||
static const std::string NODES6;
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -70,18 +70,11 @@ void DHTGetPeersMessage::doReceivedAction()
|
|||
// Check to see localhost has the contents which has same infohash
|
||||
std::vector<SharedHandle<Peer> > peers;
|
||||
peerAnnounceStorage_->getPeers(peers, infoHash_);
|
||||
SharedHandle<DHTMessage> reply;
|
||||
if(peers.empty()) {
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
getRoutingTable()->getClosestKNodes(nodes, infoHash_);
|
||||
reply =
|
||||
getMessageFactory()->createGetPeersReplyMessage
|
||||
(getRemoteNode(), nodes, token, getTransactionID());
|
||||
} else {
|
||||
reply =
|
||||
getMessageFactory()->createGetPeersReplyMessage
|
||||
(getRemoteNode(), peers, token, getTransactionID());
|
||||
}
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
getRoutingTable()->getClosestKNodes(nodes, infoHash_);
|
||||
SharedHandle<DHTMessage> reply =
|
||||
getMessageFactory()->createGetPeersReplyMessage
|
||||
(getRemoteNode(), nodes, peers, token, getTransactionID());
|
||||
getMessageDispatcher()->addMessageToQueue(reply);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,12 +57,16 @@ const std::string DHTGetPeersReplyMessage::VALUES("values");
|
|||
|
||||
const std::string DHTGetPeersReplyMessage::NODES("nodes");
|
||||
|
||||
const std::string DHTGetPeersReplyMessage::NODES6("nodes6");
|
||||
|
||||
DHTGetPeersReplyMessage::DHTGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& localNode,
|
||||
(int family,
|
||||
const SharedHandle<DHTNode>& localNode,
|
||||
const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::string& token,
|
||||
const std::string& transactionID):
|
||||
DHTResponseMessage(localNode, remoteNode, transactionID),
|
||||
family_(family),
|
||||
token_(token) {}
|
||||
|
||||
DHTGetPeersReplyMessage::~DHTGetPeersReplyMessage() {}
|
||||
|
@ -77,53 +81,63 @@ SharedHandle<Dict> DHTGetPeersReplyMessage::getResponse()
|
|||
SharedHandle<Dict> rDict = Dict::g();
|
||||
rDict->put(DHTMessage::ID, String::g(getLocalNode()->getID(), DHT_ID_LENGTH));
|
||||
rDict->put(TOKEN, token_);
|
||||
if(values_.empty()) {
|
||||
// TODO want parameter
|
||||
if(!closestKNodes_.empty()) {
|
||||
unsigned char buffer[DHTBucket::K*38];
|
||||
const int clen = bittorrent::getCompactLength(family_);
|
||||
const int unit = clen+20;
|
||||
size_t offset = 0;
|
||||
unsigned char buffer[DHTBucket::K*26];
|
||||
size_t k = 0;
|
||||
for(std::vector<SharedHandle<DHTNode> >::const_iterator i =
|
||||
closestKNodes_.begin(), eoi = closestKNodes_.end();
|
||||
i != eoi && offset < DHTBucket::K*26; ++i) {
|
||||
i != eoi && k < DHTBucket::K; ++i) {
|
||||
SharedHandle<DHTNode> node = *i;
|
||||
memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
|
||||
unsigned char compact[COMPACT_LEN_IPV6];
|
||||
int compactlen = bittorrent::packcompact
|
||||
(compact, node->getIPAddress(), node->getPort());
|
||||
if(compactlen == COMPACT_LEN_IPV4) {
|
||||
if(compactlen == clen) {
|
||||
memcpy(buffer+20+offset, compact, compactlen);
|
||||
offset += 26;
|
||||
offset += unit;
|
||||
++k;
|
||||
}
|
||||
}
|
||||
rDict->put(NODES, String::g(buffer, offset));
|
||||
} else {
|
||||
rDict->put(family_ == AF_INET?NODES:NODES6, String::g(buffer, offset));
|
||||
}
|
||||
if(!values_.empty()) {
|
||||
// Limit the size of values list. The maxmum size of UDP datagram
|
||||
// is limited to 65535 bytes. aria2 uses 20bytes token and 2byte
|
||||
// transaction ID. The size of get_peers reply message without
|
||||
// values list is 87bytes:
|
||||
// values list and nodes is 87bytes:
|
||||
//
|
||||
// d1:rd2:id20:aaaaaaaaaaaaaaaaaaaa5:token20:aaaaaaaaaaaaaaaaaaaa
|
||||
// 6:valueslee1:t2:bb1:y1:re
|
||||
//
|
||||
// nodes are 38 bytes per host for IPv6 and the number of hosts is
|
||||
// K(=8) max. So without values list, we already 87+38*8+4 = 395.
|
||||
//
|
||||
// Because of Path MTU Discovery, UDP packet size which need not
|
||||
// to be fragmented is much smaller. Since Linux uses Path MTU
|
||||
// Dicoverry by default and returning ICMP message might be
|
||||
// filtered, we should avoid fragmentation. MTU of pppoe is 1492
|
||||
// max according to RFC2516. We use maximum packet size to be
|
||||
// 1000. Since it contains 20 bytes IP header and 8 bytes UDP
|
||||
// header and 87 bytes reply message template described above, We
|
||||
// can carry (1000-28-87)/8 = 110 peer info. Since DHT spec
|
||||
// 1024. Since it contains 20 bytes IP header and 8 bytes UDP
|
||||
// header and 395 bytes reply message template described above, We
|
||||
// can carry (1024-28-395)/(18+3) = 28 peer info. Since DHT spec
|
||||
// doesn't specify the maximum size of token, reply message
|
||||
// template may get bigger than 87 bytes. So we use 100 as maximum
|
||||
// template may get bigger than 395 bytes. So we use 25 as maximum
|
||||
// number of peer info that a message can carry.
|
||||
static const size_t MAX_VALUES_SIZE = 100;
|
||||
static const size_t MAX_VALUES_SIZE = 25;
|
||||
SharedHandle<List> valuesList = List::g();
|
||||
for(std::vector<SharedHandle<Peer> >::const_iterator i = values_.begin(),
|
||||
eoi = values_.end(); i != eoi && valuesList->size() < MAX_VALUES_SIZE;
|
||||
++i) {
|
||||
const SharedHandle<Peer>& peer = *i;
|
||||
unsigned char compact[COMPACT_LEN_IPV6];
|
||||
const int clen = bittorrent::getCompactLength(family_);
|
||||
int compactlen = bittorrent::packcompact
|
||||
(compact, peer->getIPAddress(), peer->getPort());
|
||||
if(compactlen == COMPACT_LEN_IPV4) {
|
||||
if(compactlen == clen) {
|
||||
valuesList->append(String::g(compact, compactlen));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ class Peer;
|
|||
|
||||
class DHTGetPeersReplyMessage:public DHTResponseMessage {
|
||||
private:
|
||||
int family_;
|
||||
|
||||
std::string token_;
|
||||
|
||||
std::vector<SharedHandle<DHTNode> > closestKNodes_;
|
||||
|
@ -55,7 +57,8 @@ private:
|
|||
protected:
|
||||
virtual std::string toStringOptional() const;
|
||||
public:
|
||||
DHTGetPeersReplyMessage(const SharedHandle<DHTNode>& localNode,
|
||||
DHTGetPeersReplyMessage(int family,
|
||||
const SharedHandle<DHTNode>& localNode,
|
||||
const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::string& token,
|
||||
const std::string& transactionID);
|
||||
|
@ -103,6 +106,8 @@ public:
|
|||
static const std::string VALUES;
|
||||
|
||||
static const std::string NODES;
|
||||
|
||||
static const std::string NODES6;
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -94,12 +94,6 @@ public:
|
|||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<DHTNode> >& closestKNodes,
|
||||
const std::string& token,
|
||||
const std::string& transactionID) = 0;
|
||||
|
||||
virtual SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID) = 0;
|
||||
|
|
|
@ -64,7 +64,8 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
DHTMessageFactoryImpl::DHTMessageFactoryImpl():
|
||||
DHTMessageFactoryImpl::DHTMessageFactoryImpl(int family):
|
||||
family_(family),
|
||||
logger_(LogFactory::getInstance()) {}
|
||||
|
||||
DHTMessageFactoryImpl::~DHTMessageFactoryImpl() {}
|
||||
|
@ -261,21 +262,7 @@ DHTMessageFactoryImpl::createResponseMessage
|
|||
} else if(messageType == DHTFindNodeReplyMessage::FIND_NODE) {
|
||||
msg = createFindNodeReplyMessage(remoteNode, dict, transactionID->s());
|
||||
} else if(messageType == DHTGetPeersReplyMessage::GET_PEERS) {
|
||||
const List* valuesList =
|
||||
asList(rDict->get(DHTGetPeersReplyMessage::VALUES));
|
||||
if(valuesList) {
|
||||
msg = createGetPeersReplyMessageWithValues
|
||||
(remoteNode, dict, transactionID->s());
|
||||
} else {
|
||||
const String* nodes = asString
|
||||
(rDict->get(DHTGetPeersReplyMessage::NODES));
|
||||
if(nodes) {
|
||||
msg = createGetPeersReplyMessageWithNodes
|
||||
(remoteNode, dict, transactionID->s());
|
||||
} else {
|
||||
throw DL_ABORT_EX("Malformed DHT message: missing nodes/values");
|
||||
}
|
||||
}
|
||||
msg = createGetPeersReplyMessage(remoteNode, dict, transactionID->s());
|
||||
} else if(messageType == DHTAnnouncePeerReplyMessage::ANNOUNCE_PEER) {
|
||||
msg = createAnnouncePeerReplyMessage(remoteNode, transactionID->s());
|
||||
} else {
|
||||
|
@ -349,23 +336,26 @@ DHTMessageFactoryImpl::createFindNodeReplyMessage
|
|||
const std::string& transactionID)
|
||||
{
|
||||
SharedHandle<DHTFindNodeReplyMessage> m
|
||||
(new DHTFindNodeReplyMessage(localNode_, remoteNode, transactionID));
|
||||
(new DHTFindNodeReplyMessage
|
||||
(family_, localNode_, remoteNode, transactionID));
|
||||
m->setClosestKNodes(closestKNodes);
|
||||
setCommonProperty(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
std::vector<SharedHandle<DHTNode> >
|
||||
DHTMessageFactoryImpl::extractNodes(const unsigned char* src, size_t length)
|
||||
void DHTMessageFactoryImpl::extractNodes
|
||||
(std::vector<SharedHandle<DHTNode> >& nodes,
|
||||
const unsigned char* src, size_t length)
|
||||
{
|
||||
if(length%26 != 0) {
|
||||
throw DL_ABORT_EX("Nodes length is not multiple of 26");
|
||||
int unit = bittorrent::getCompactLength(family_)+20;
|
||||
if(length%unit != 0) {
|
||||
throw DL_ABORT_EX
|
||||
(StringFormat("Nodes length is not multiple of %d", unit).str());
|
||||
}
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
for(size_t offset = 0; offset < length; offset += 26) {
|
||||
for(size_t offset = 0; offset < length; offset += unit) {
|
||||
SharedHandle<DHTNode> node(new DHTNode(src+offset));
|
||||
std::pair<std::string, uint16_t> addr =
|
||||
bittorrent::unpackcompact(src+offset+DHT_ID_LENGTH, AF_INET);
|
||||
bittorrent::unpackcompact(src+offset+DHT_ID_LENGTH, family_);
|
||||
if(addr.first.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -373,7 +363,6 @@ DHTMessageFactoryImpl::extractNodes(const unsigned char* src, size_t length)
|
|||
node->setPort(addr.second);
|
||||
nodes.push_back(node);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
|
@ -383,10 +372,13 @@ DHTMessageFactoryImpl::createFindNodeReplyMessage
|
|||
const std::string& transactionID)
|
||||
{
|
||||
const String* nodesData =
|
||||
getString(getDictionary(dict, DHTResponseMessage::R),
|
||||
DHTFindNodeReplyMessage::NODES);
|
||||
std::vector<SharedHandle<DHTNode> > nodes =
|
||||
extractNodes(nodesData->uc(), nodesData->s().size());
|
||||
asString(getDictionary(dict, DHTResponseMessage::R)->
|
||||
get(family_ == AF_INET?DHTFindNodeReplyMessage::NODES:
|
||||
DHTFindNodeReplyMessage::NODES6));
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
if(nodesData) {
|
||||
extractNodes(nodes, nodesData->uc(), nodesData->s().size());
|
||||
}
|
||||
return createFindNodeReplyMessage(remoteNode, nodes, transactionID);
|
||||
}
|
||||
|
||||
|
@ -405,68 +397,55 @@ DHTMessageFactoryImpl::createGetPeersMessage
|
|||
}
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
DHTMessageFactoryImpl::createGetPeersReplyMessageWithNodes
|
||||
DHTMessageFactoryImpl::createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const Dict* dict,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
const Dict* rDict = getDictionary(dict, DHTResponseMessage::R);
|
||||
const String* nodesData = getString(rDict, DHTGetPeersReplyMessage::NODES);
|
||||
std::vector<SharedHandle<DHTNode> > nodes = extractNodes
|
||||
(nodesData->uc(), nodesData->s().size());
|
||||
const String* nodesData =
|
||||
asString(rDict->get(family_ == AF_INET?DHTGetPeersReplyMessage::NODES:
|
||||
DHTGetPeersReplyMessage::NODES6));
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
if(nodesData) {
|
||||
extractNodes(nodes, nodesData->uc(), nodesData->s().size());
|
||||
}
|
||||
const List* valuesList =
|
||||
asList(rDict->get(DHTGetPeersReplyMessage::VALUES));
|
||||
std::vector<SharedHandle<Peer> > peers;
|
||||
size_t clen = bittorrent::getCompactLength(family_);
|
||||
if(valuesList) {
|
||||
for(List::ValueType::const_iterator i = valuesList->begin(),
|
||||
eoi = valuesList->end(); i != eoi; ++i) {
|
||||
const String* data = asString(*i);
|
||||
if(data && data->s().size() == clen) {
|
||||
std::pair<std::string, uint16_t> addr =
|
||||
bittorrent::unpackcompact(data->uc(), family_);
|
||||
if(addr.first.empty()) {
|
||||
continue;
|
||||
}
|
||||
SharedHandle<Peer> peer(new Peer(addr.first, addr.second));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
const String* token = getString(rDict, DHTGetPeersReplyMessage::TOKEN);
|
||||
return createGetPeersReplyMessage
|
||||
(remoteNode, nodes, token->s(), transactionID);
|
||||
(remoteNode, nodes, peers, token->s(), transactionID);
|
||||
}
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
DHTMessageFactoryImpl::createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<DHTNode> >& closestKNodes,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
SharedHandle<DHTGetPeersReplyMessage> m
|
||||
(new DHTGetPeersReplyMessage(localNode_, remoteNode, token, transactionID));
|
||||
m->setClosestKNodes(closestKNodes);
|
||||
setCommonProperty(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
DHTMessageFactoryImpl::createGetPeersReplyMessageWithValues
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const Dict* dict,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
const Dict* rDict = getDictionary(dict, DHTResponseMessage::R);
|
||||
const List* valuesList = getList(rDict,
|
||||
DHTGetPeersReplyMessage::VALUES);
|
||||
std::vector<SharedHandle<Peer> > peers;
|
||||
for(List::ValueType::const_iterator i = valuesList->begin(),
|
||||
eoi = valuesList->end(); i != eoi; ++i) {
|
||||
const String* data = asString(*i);
|
||||
if(data && data->s().size() == 6) {
|
||||
std::pair<std::string, uint16_t> addr =
|
||||
bittorrent::unpackcompact(data->uc(), AF_INET);
|
||||
SharedHandle<Peer> peer(new Peer(addr.first, addr.second));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
}
|
||||
const String* token = getString(rDict, DHTGetPeersReplyMessage::TOKEN);
|
||||
return createGetPeersReplyMessage
|
||||
(remoteNode, peers, token->s(), transactionID);
|
||||
}
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
DHTMessageFactoryImpl::createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<Peer> >& values,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
SharedHandle<DHTGetPeersReplyMessage> m
|
||||
(new DHTGetPeersReplyMessage(localNode_, remoteNode, token, transactionID));
|
||||
(new DHTGetPeersReplyMessage
|
||||
(family_, localNode_, remoteNode, token, transactionID));
|
||||
m->setClosestKNodes(closestKNodes);
|
||||
m->setValues(values);
|
||||
setCommonProperty(m);
|
||||
return m;
|
||||
|
|
|
@ -51,6 +51,8 @@ class DHTAbstractMessage;
|
|||
|
||||
class DHTMessageFactoryImpl:public DHTMessageFactory {
|
||||
private:
|
||||
int family_;
|
||||
|
||||
SharedHandle<DHTNode> localNode_;
|
||||
|
||||
WeakHandle<DHTConnection> connection_;
|
||||
|
@ -73,13 +75,14 @@ private:
|
|||
|
||||
void validatePort(const Integer* i) const;
|
||||
|
||||
std::vector<SharedHandle<DHTNode> >
|
||||
extractNodes(const unsigned char* src, size_t length);
|
||||
void extractNodes
|
||||
(std::vector<SharedHandle<DHTNode> >& nodes,
|
||||
const unsigned char* src, size_t length);
|
||||
|
||||
void setCommonProperty(const SharedHandle<DHTAbstractMessage>& m);
|
||||
|
||||
public:
|
||||
DHTMessageFactoryImpl();
|
||||
DHTMessageFactoryImpl(int family);
|
||||
|
||||
virtual ~DHTMessageFactoryImpl();
|
||||
|
||||
|
@ -127,25 +130,15 @@ public:
|
|||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<DHTNode> >& closestKNodes,
|
||||
const std::string& token,
|
||||
const std::string& transactionID);
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessageWithNodes(const SharedHandle<DHTNode>& remoteNode,
|
||||
const Dict* dict,
|
||||
const std::string& transactionID);
|
||||
|
||||
virtual SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID);
|
||||
|
||||
SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessageWithValues(const SharedHandle<DHTNode>& remoteNode,
|
||||
const Dict* dict,
|
||||
const std::string& transactionID);
|
||||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const Dict* dict,
|
||||
const std::string& transactionID);
|
||||
|
||||
virtual SharedHandle<DHTQueryMessage>
|
||||
createAnnouncePeerMessage(const SharedHandle<DHTNode>& remoteNode,
|
||||
|
|
|
@ -84,19 +84,24 @@ DHTMessageTracker::messageArrived
|
|||
logger_->debug("Tracker entry found.");
|
||||
}
|
||||
SharedHandle<DHTNode> targetNode = entry->getTargetNode();
|
||||
try {
|
||||
SharedHandle<DHTResponseMessage> message =
|
||||
factory_->createResponseMessage(entry->getMessageType(), dict,
|
||||
targetNode->getIPAddress(),
|
||||
targetNode->getPort());
|
||||
|
||||
SharedHandle<DHTResponseMessage> message =
|
||||
factory_->createResponseMessage(entry->getMessageType(), dict,
|
||||
targetNode->getIPAddress(),
|
||||
targetNode->getPort());
|
||||
|
||||
int64_t rtt = entry->getElapsedMillis();
|
||||
if(logger_->debug()) {
|
||||
logger_->debug("RTT is %s", util::itos(rtt).c_str());
|
||||
int64_t rtt = entry->getElapsedMillis();
|
||||
if(logger_->debug()) {
|
||||
logger_->debug("RTT is %s", util::itos(rtt).c_str());
|
||||
}
|
||||
message->getRemoteNode()->updateRTT(rtt);
|
||||
SharedHandle<DHTMessageCallback> callback = entry->getCallback();
|
||||
return std::make_pair(message, callback);
|
||||
} catch(RecoverableException& e) {
|
||||
entry->getCallback()->onTimeout(targetNode);
|
||||
return std::pair<SharedHandle<DHTResponseMessage>,
|
||||
SharedHandle<DHTMessageCallback> >();
|
||||
}
|
||||
message->getRemoteNode()->updateRTT(rtt);
|
||||
SharedHandle<DHTMessageCallback> callback = entry->getCallback();
|
||||
return std::make_pair(message, callback);
|
||||
}
|
||||
}
|
||||
if(logger_->debug()) {
|
||||
|
|
|
@ -49,17 +49,30 @@ namespace aria2 {
|
|||
|
||||
DHTRegistry::Data DHTRegistry::data_;
|
||||
|
||||
DHTRegistry::Data DHTRegistry::data6_;
|
||||
|
||||
void DHTRegistry::clear(DHTRegistry::Data& data)
|
||||
{
|
||||
data.initialized = false;
|
||||
data.localNode.reset();
|
||||
data.routingTable.reset();
|
||||
data.taskQueue.reset();
|
||||
data.taskFactory.reset();
|
||||
data.peerAnnounceStorage.reset();
|
||||
data.tokenTracker.reset();
|
||||
data.messageDispatcher.reset();
|
||||
data.messageReceiver.reset();
|
||||
data.messageFactory.reset();
|
||||
}
|
||||
|
||||
void DHTRegistry::clearData()
|
||||
{
|
||||
data_.localNode.reset();
|
||||
data_.routingTable.reset();
|
||||
data_.taskQueue.reset();
|
||||
data_.taskFactory.reset();
|
||||
data_.peerAnnounceStorage.reset();
|
||||
data_.tokenTracker.reset();
|
||||
data_.messageDispatcher.reset();
|
||||
data_.messageReceiver.reset();
|
||||
data_.messageFactory.reset();
|
||||
clear(data_);
|
||||
}
|
||||
|
||||
void DHTRegistry::clearData6()
|
||||
{
|
||||
clear(data6_);
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -53,6 +53,8 @@ class DHTMessageFactory;
|
|||
class DHTRegistry {
|
||||
private:
|
||||
struct Data {
|
||||
bool initialized;
|
||||
|
||||
SharedHandle<DHTNode> localNode;
|
||||
|
||||
SharedHandle<DHTRoutingTable> routingTable;
|
||||
|
@ -70,9 +72,15 @@ private:
|
|||
SharedHandle<DHTMessageReceiver> messageReceiver;
|
||||
|
||||
SharedHandle<DHTMessageFactory> messageFactory;
|
||||
|
||||
Data():initialized(false) {}
|
||||
};
|
||||
|
||||
static Data data_;
|
||||
static Data data6_;
|
||||
|
||||
static void clear(Data& data);
|
||||
|
||||
DHTRegistry();
|
||||
public:
|
||||
static const Data& getData()
|
||||
|
@ -86,6 +94,38 @@ public:
|
|||
}
|
||||
|
||||
static void clearData();
|
||||
|
||||
static bool isInitialized()
|
||||
{
|
||||
return data_.initialized;
|
||||
}
|
||||
|
||||
static void setInitialized(bool f)
|
||||
{
|
||||
data_.initialized = f;
|
||||
}
|
||||
|
||||
static const Data& getData6()
|
||||
{
|
||||
return data6_;
|
||||
}
|
||||
|
||||
static Data& getMutableData6()
|
||||
{
|
||||
return data6_;
|
||||
}
|
||||
|
||||
static void clearData6();
|
||||
|
||||
static bool isInitialized6()
|
||||
{
|
||||
return data6_.initialized;
|
||||
}
|
||||
|
||||
static void setInitialized6(bool f)
|
||||
{
|
||||
data6_.initialized = f;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
DHTRoutingTableDeserializer::DHTRoutingTableDeserializer() {}
|
||||
DHTRoutingTableDeserializer::DHTRoutingTableDeserializer(int family):
|
||||
family_(family) {}
|
||||
|
||||
DHTRoutingTableDeserializer::~DHTRoutingTableDeserializer() {}
|
||||
|
||||
|
@ -99,7 +100,7 @@ void DHTRoutingTableDeserializer::deserialize(std::istream& in)
|
|||
headerCompat[6] = 0;
|
||||
headerCompat[7] = 0x02;
|
||||
|
||||
char zero[8];
|
||||
char zero[18];
|
||||
memset(zero, 0, sizeof(zero));
|
||||
|
||||
int version;
|
||||
|
@ -159,44 +160,39 @@ void DHTRoutingTableDeserializer::deserialize(std::istream& in)
|
|||
|
||||
std::vector<SharedHandle<DHTNode> > nodes;
|
||||
// nodes
|
||||
const int compactlen = bittorrent::getCompactLength(family_);
|
||||
for(size_t i = 0; i < numNodes; ++i) {
|
||||
// Currently, only IPv4 addresses are supported.
|
||||
// 1byte compact peer info length
|
||||
uint8_t peerInfoLen;
|
||||
in >> peerInfoLen;
|
||||
if(peerInfoLen != 6) {
|
||||
if(peerInfoLen != compactlen) {
|
||||
// skip this entry
|
||||
readBytes(buf, buf.size(), in, 42+7+6);
|
||||
CHECK_STREAM(in, 42+7+6);
|
||||
readBytes(buf, buf.size(), in, 7+48);
|
||||
CHECK_STREAM(in, 7+48);
|
||||
continue;
|
||||
}
|
||||
// 7bytes reserved
|
||||
readBytes(buf, buf.size(), in, 7);
|
||||
CHECK_STREAM(in, 7);
|
||||
// 6bytes compact peer info
|
||||
readBytes(buf, buf.size(), in, 6);
|
||||
CHECK_STREAM(in, 6);
|
||||
if(memcmp(zero, buf, 6) == 0) {
|
||||
// compactlen bytes compact peer info
|
||||
readBytes(buf, buf.size(), in, compactlen);
|
||||
CHECK_STREAM(in, compactlen);
|
||||
if(memcmp(zero, buf, compactlen) == 0) {
|
||||
// skip this entry
|
||||
readBytes(buf, buf.size(), in, 42);
|
||||
CHECK_STREAM(in, 42);
|
||||
readBytes(buf, buf.size(), in, 48-compactlen);
|
||||
CHECK_STREAM(in, 48-compactlen);
|
||||
continue;
|
||||
}
|
||||
// TODO DHT6 protocol family should be configurable.
|
||||
std::pair<std::string, uint16_t> peer =
|
||||
bittorrent::unpackcompact(buf, AF_INET);
|
||||
bittorrent::unpackcompact(buf, family_);
|
||||
if(peer.first.empty()) {
|
||||
// skip this entry
|
||||
readBytes(buf, buf.size(), in, 42);
|
||||
CHECK_STREAM(in, 42);
|
||||
readBytes(buf, buf.size(), in, 48-compactlen);
|
||||
CHECK_STREAM(in, 48-compactlen);
|
||||
continue;
|
||||
}
|
||||
// 2bytes reserved
|
||||
readBytes(buf, buf.size(), in, 2);
|
||||
CHECK_STREAM(in, 2);
|
||||
// 16byte reserved
|
||||
readBytes(buf, buf.size(), in, 16);
|
||||
CHECK_STREAM(in, 16);
|
||||
// 24-compactlen bytes reserved
|
||||
readBytes(buf, buf.size(), in, 24-compactlen);
|
||||
// node ID
|
||||
readBytes(buf, buf.size(), in, DHT_ID_LENGTH);
|
||||
CHECK_STREAM(in, DHT_ID_LENGTH);
|
||||
|
|
|
@ -49,13 +49,15 @@ class DHTNode;
|
|||
|
||||
class DHTRoutingTableDeserializer {
|
||||
private:
|
||||
int family_;
|
||||
|
||||
SharedHandle<DHTNode> localNode_;
|
||||
|
||||
std::vector<SharedHandle<DHTNode> > nodes_;
|
||||
|
||||
Time serializedTime_;
|
||||
public:
|
||||
DHTRoutingTableDeserializer();
|
||||
DHTRoutingTableDeserializer(int family);
|
||||
|
||||
~DHTRoutingTableDeserializer();
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
DHTRoutingTableSerializer::DHTRoutingTableSerializer() {}
|
||||
DHTRoutingTableSerializer::DHTRoutingTableSerializer(int family):
|
||||
family_(family) {}
|
||||
|
||||
DHTRoutingTableSerializer::~DHTRoutingTableSerializer() {}
|
||||
|
||||
|
@ -79,7 +80,7 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o)
|
|||
header[6] = 0;
|
||||
header[7] = 0x03;
|
||||
|
||||
char zero[16];
|
||||
char zero[18];
|
||||
memset(zero, 0, sizeof(zero));
|
||||
|
||||
o.write(header, 8);
|
||||
|
@ -101,29 +102,26 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o)
|
|||
// 4bytes reserved
|
||||
o.write(zero, 4);
|
||||
|
||||
const int clen = bittorrent::getCompactLength(family_);
|
||||
// nodes
|
||||
for(std::vector<SharedHandle<DHTNode> >::const_iterator i = nodes_.begin(),
|
||||
eoi = nodes_.end(); i != eoi; ++i) {
|
||||
const SharedHandle<DHTNode>& node = *i;
|
||||
// Currently, only IPv4 addresses are saved.
|
||||
// 6bytes: write IP address + port in Compact IP-address/port info form.
|
||||
// Write IP address + port in Compact IP-address/port info form.
|
||||
unsigned char compactPeer[COMPACT_LEN_IPV6];
|
||||
int compactlen = bittorrent::packcompact
|
||||
(compactPeer, node->getIPAddress(), node->getPort());
|
||||
if(compactlen != COMPACT_LEN_IPV4) {
|
||||
compactlen = COMPACT_LEN_IPV4;
|
||||
memset(compactPeer, 0, COMPACT_LEN_IPV4);
|
||||
if(compactlen != clen) {
|
||||
memset(compactPeer, 0, clen);
|
||||
}
|
||||
// 1byte compact peer format length
|
||||
o << static_cast<uint8_t>(compactlen);
|
||||
o << static_cast<uint8_t>(clen);
|
||||
// 7bytes reserved
|
||||
o.write(zero, 7);
|
||||
// 6 bytes compact peer
|
||||
o.write(reinterpret_cast<const char*>(compactPeer), compactlen);
|
||||
// 2bytes reserved
|
||||
o.write(zero, 2);
|
||||
// 16bytes reserved
|
||||
o.write(zero, 16);
|
||||
// clen bytes compact peer
|
||||
o.write(reinterpret_cast<const char*>(compactPeer), clen);
|
||||
// 24-clen bytes reserved
|
||||
o.write(zero, 24-clen);
|
||||
// 20bytes: node ID
|
||||
o.write(reinterpret_cast<const char*>(node->getID()), DHT_ID_LENGTH);
|
||||
// 4bytes reserved
|
||||
|
|
|
@ -48,11 +48,13 @@ class DHTNode;
|
|||
|
||||
class DHTRoutingTableSerializer {
|
||||
private:
|
||||
int family_;
|
||||
|
||||
SharedHandle<DHTNode> localNode_;
|
||||
|
||||
std::vector<SharedHandle<DHTNode> > nodes_;
|
||||
public:
|
||||
DHTRoutingTableSerializer();
|
||||
DHTRoutingTableSerializer(int family);
|
||||
|
||||
~DHTRoutingTableSerializer();
|
||||
|
||||
|
|
|
@ -79,16 +79,18 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
// TODO DownloadEngine should hold this flag.
|
||||
bool DHTSetup::initialized_ = false;
|
||||
|
||||
DHTSetup::DHTSetup():logger_(LogFactory::getInstance()) {}
|
||||
|
||||
DHTSetup::~DHTSetup() {}
|
||||
|
||||
void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
||||
void DHTSetup::setup
|
||||
(std::vector<Command*>& commands, DownloadEngine* e, int family)
|
||||
{
|
||||
if(initialized_) {
|
||||
if(family != AF_INET && family != AF_INET6) {
|
||||
return;
|
||||
}
|
||||
if((family == AF_INET && DHTRegistry::isInitialized()) ||
|
||||
(family == AF_INET6 && DHTRegistry::isInitialized6())) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -98,8 +100,10 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
|
||||
SharedHandle<DHTNode> localNode;
|
||||
|
||||
DHTRoutingTableDeserializer deserializer;
|
||||
std::string dhtFile = e->getOption()->get(PREF_DHT_FILE_PATH);
|
||||
DHTRoutingTableDeserializer deserializer(family);
|
||||
const std::string& dhtFile =
|
||||
e->getOption()->get(family == AF_INET?PREF_DHT_FILE_PATH:
|
||||
PREF_DHT_FILE_PATH6);
|
||||
try {
|
||||
std::ifstream in(dhtFile.c_str(), std::ios::binary);
|
||||
if(!in) {
|
||||
|
@ -115,12 +119,15 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
localNode.reset(new DHTNode());
|
||||
}
|
||||
|
||||
SharedHandle<DHTConnectionImpl> connection(new DHTConnectionImpl());
|
||||
SharedHandle<DHTConnectionImpl> connection(new DHTConnectionImpl(family));
|
||||
{
|
||||
IntSequence seq =
|
||||
util::parseIntRange(e->getOption()->get(PREF_DHT_LISTEN_PORT));
|
||||
uint16_t port;
|
||||
if(!connection->bind(port, seq)) {
|
||||
const std::string& addr =
|
||||
e->getOption()->get(family == AF_INET?PREF_DHT_LISTEN_ADDR:
|
||||
PREF_DHT_LISTEN_ADDR6);
|
||||
if(!connection->bind(port, addr, seq)) {
|
||||
throw DL_ABORT_EX("Error occurred while binding port for DHT");
|
||||
}
|
||||
localNode->setPort(port);
|
||||
|
@ -131,7 +138,8 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
}
|
||||
SharedHandle<DHTRoutingTable> routingTable(new DHTRoutingTable(localNode));
|
||||
|
||||
SharedHandle<DHTMessageFactoryImpl> factory(new DHTMessageFactoryImpl());
|
||||
SharedHandle<DHTMessageFactoryImpl> factory
|
||||
(new DHTMessageFactoryImpl(family));
|
||||
|
||||
SharedHandle<DHTMessageTracker> tracker(new DHTMessageTracker());
|
||||
|
||||
|
@ -179,16 +187,27 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
factory->setLocalNode(localNode);
|
||||
|
||||
// assign them into DHTRegistry
|
||||
DHTRegistry::getMutableData().localNode = localNode;
|
||||
DHTRegistry::getMutableData().routingTable = routingTable;
|
||||
DHTRegistry::getMutableData().taskQueue = taskQueue;
|
||||
DHTRegistry::getMutableData().taskFactory = taskFactory;
|
||||
DHTRegistry::getMutableData().peerAnnounceStorage = peerAnnounceStorage;
|
||||
DHTRegistry::getMutableData().tokenTracker = tokenTracker;
|
||||
DHTRegistry::getMutableData().messageDispatcher = dispatcher;
|
||||
DHTRegistry::getMutableData().messageReceiver = receiver;
|
||||
DHTRegistry::getMutableData().messageFactory = factory;
|
||||
|
||||
if(family == AF_INET) {
|
||||
DHTRegistry::getMutableData().localNode = localNode;
|
||||
DHTRegistry::getMutableData().routingTable = routingTable;
|
||||
DHTRegistry::getMutableData().taskQueue = taskQueue;
|
||||
DHTRegistry::getMutableData().taskFactory = taskFactory;
|
||||
DHTRegistry::getMutableData().peerAnnounceStorage = peerAnnounceStorage;
|
||||
DHTRegistry::getMutableData().tokenTracker = tokenTracker;
|
||||
DHTRegistry::getMutableData().messageDispatcher = dispatcher;
|
||||
DHTRegistry::getMutableData().messageReceiver = receiver;
|
||||
DHTRegistry::getMutableData().messageFactory = factory;
|
||||
} else {
|
||||
DHTRegistry::getMutableData6().localNode = localNode;
|
||||
DHTRegistry::getMutableData6().routingTable = routingTable;
|
||||
DHTRegistry::getMutableData6().taskQueue = taskQueue;
|
||||
DHTRegistry::getMutableData6().taskFactory = taskFactory;
|
||||
DHTRegistry::getMutableData6().peerAnnounceStorage = peerAnnounceStorage;
|
||||
DHTRegistry::getMutableData6().tokenTracker = tokenTracker;
|
||||
DHTRegistry::getMutableData6().messageDispatcher = dispatcher;
|
||||
DHTRegistry::getMutableData6().messageReceiver = receiver;
|
||||
DHTRegistry::getMutableData6().messageFactory = factory;
|
||||
}
|
||||
// add deserialized nodes to routing table
|
||||
const std::vector<SharedHandle<DHTNode> >& desnodes =
|
||||
deserializer.getNodes();
|
||||
|
@ -206,11 +225,16 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
taskQueue->addPeriodicTask1(task);
|
||||
}
|
||||
|
||||
if(!e->getOption()->get(PREF_DHT_ENTRY_POINT_HOST).empty()) {
|
||||
const std::string& prefEntryPointHost =
|
||||
family == AF_INET?PREF_DHT_ENTRY_POINT_HOST:PREF_DHT_ENTRY_POINT_HOST6;
|
||||
if(!e->getOption()->get(prefEntryPointHost).empty()) {
|
||||
{
|
||||
const std::string& prefEntryPointPort =
|
||||
family == AF_INET?PREF_DHT_ENTRY_POINT_PORT:
|
||||
PREF_DHT_ENTRY_POINT_PORT6;
|
||||
std::pair<std::string, uint16_t> addr
|
||||
(e->getOption()->get(PREF_DHT_ENTRY_POINT_HOST),
|
||||
e->getOption()->getAsInt(PREF_DHT_ENTRY_POINT_PORT));
|
||||
(e->getOption()->get(prefEntryPointHost),
|
||||
e->getOption()->getAsInt(prefEntryPointPort));
|
||||
std::vector<std::pair<std::string, uint16_t> > entryPoints;
|
||||
entryPoints.push_back(addr);
|
||||
DHTEntryPointNameResolveCommand* command =
|
||||
|
@ -258,24 +282,27 @@ void DHTSetup::setup(std::vector<Command*>& commands, DownloadEngine* e)
|
|||
}
|
||||
{
|
||||
DHTAutoSaveCommand* command =
|
||||
new DHTAutoSaveCommand(e->newCUID(), e, 30*60);
|
||||
new DHTAutoSaveCommand(e->newCUID(), e, family, 30*60);
|
||||
command->setLocalNode(localNode);
|
||||
command->setRoutingTable(routingTable);
|
||||
tempCommands->push_back(command);
|
||||
}
|
||||
initialized_ = true;
|
||||
if(family == AF_INET) {
|
||||
DHTRegistry::setInitialized(true);
|
||||
} else {
|
||||
DHTRegistry::setInitialized6(true);
|
||||
}
|
||||
commands.insert(commands.end(), tempCommands->begin(), tempCommands->end());
|
||||
tempCommands->clear();
|
||||
} catch(RecoverableException& e) {
|
||||
logger_->error("Exception caught while initializing DHT functionality."
|
||||
" DHT is disabled.", e);
|
||||
DHTRegistry::clearData();
|
||||
if(family == AF_INET) {
|
||||
DHTRegistry::clearData();
|
||||
} else {
|
||||
DHTRegistry::clearData6();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DHTSetup::initialized()
|
||||
{
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -45,18 +45,13 @@ class Command;
|
|||
|
||||
class DHTSetup {
|
||||
private:
|
||||
static bool initialized_;
|
||||
|
||||
Logger* logger_;
|
||||
|
||||
public:
|
||||
DHTSetup();
|
||||
|
||||
~DHTSetup();
|
||||
|
||||
void setup(std::vector<Command*>& commands, DownloadEngine* e);
|
||||
|
||||
static bool initialized();
|
||||
void setup(std::vector<Command*>& commands, DownloadEngine* e, int family);
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -223,7 +223,7 @@ SharedHandle<SocketCore> FtpConnection::createServerSocket()
|
|||
std::pair<std::string, uint16_t> addrinfo;
|
||||
socket_->getAddrInfo(addrinfo);
|
||||
SharedHandle<SocketCore> serverSocket(new SocketCore());
|
||||
serverSocket->bind(addrinfo.first, 0);
|
||||
serverSocket->bind(addrinfo.first, 0, AF_UNSPEC);
|
||||
serverSocket->beginListen();
|
||||
serverSocket->setNonBlockingMode();
|
||||
return serverSocket;
|
||||
|
|
|
@ -56,7 +56,7 @@ bool LpdMessageReceiver::init(const std::string& localAddr)
|
|||
// Binding multicast address fails under Windows.
|
||||
socket_->bindWithFamily(multicastPort_, AF_INET);
|
||||
#else // !__MINGW32__
|
||||
socket_->bind(multicastAddress_, multicastPort_);
|
||||
socket_->bind(multicastAddress_, multicastPort_, AF_INET);
|
||||
#endif // !__MINGW32__
|
||||
if(logger_->debug()) {
|
||||
logger_->debug("Joining multicast group. %s:%u, localAddr=%s",
|
||||
|
|
|
@ -1325,6 +1325,16 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
|||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new HostPortOptionHandler
|
||||
(PREF_DHT_ENTRY_POINT6,
|
||||
TEXT_DHT_ENTRY_POINT6,
|
||||
NO_DEFAULT_VALUE,
|
||||
PREF_DHT_ENTRY_POINT_HOST6,
|
||||
PREF_DHT_ENTRY_POINT_PORT6));
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||
(PREF_DHT_FILE_PATH,
|
||||
|
@ -1334,6 +1344,34 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
|||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||
(PREF_DHT_FILE_PATH6,
|
||||
TEXT_DHT_FILE_PATH6,
|
||||
util::getHomeDir()+"/.aria2/dht6.dat",
|
||||
"/PATH/TO/DHT_DAT"));
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||
(PREF_DHT_LISTEN_ADDR,
|
||||
NO_DESCRIPTION,
|
||||
NO_DEFAULT_VALUE));
|
||||
op->hide();
|
||||
op->addTag(TAG_BASIC);
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||
(PREF_DHT_LISTEN_ADDR6,
|
||||
TEXT_DHT_LISTEN_ADDR6,
|
||||
NO_DEFAULT_VALUE));
|
||||
op->addTag(TAG_BASIC);
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new IntegerRangeOptionHandler
|
||||
(PREF_DHT_LISTEN_PORT,
|
||||
|
@ -1363,6 +1401,16 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
|||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new BooleanOptionHandler
|
||||
(PREF_ENABLE_DHT6,
|
||||
TEXT_ENABLE_DHT6,
|
||||
V_FALSE,
|
||||
OptionHandler::OPT_ARG));
|
||||
op->addTag(TAG_BASIC);
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new BooleanOptionHandler
|
||||
(PREF_ENABLE_PEER_EXCHANGE,
|
||||
|
|
|
@ -522,17 +522,18 @@ public:
|
|||
|
||||
virtual void parseArg(Option& option, const std::string& optarg)
|
||||
{
|
||||
std::pair<std::string, std::string> proxy = util::split(optarg, ":");
|
||||
int32_t port = util::parseInt(proxy.second);
|
||||
if(proxy.first.empty() || proxy.second.empty() ||
|
||||
port <= 0 || 65535 < port) {
|
||||
throw DL_ABORT_EX(_("unrecognized proxy format"));
|
||||
std::string uri = "http://";
|
||||
uri += optarg;
|
||||
Request req;
|
||||
if(!req.setUri(uri)) {
|
||||
throw DL_ABORT_EX(_("Unrecognized format"));
|
||||
}
|
||||
option.put(optName_, optarg);
|
||||
setHostAndPort(option, proxy.first, port);
|
||||
setHostAndPort(option, req.getHost(), req.getPort());
|
||||
}
|
||||
|
||||
void setHostAndPort(Option& option, const std::string& hostname, uint16_t port)
|
||||
void setHostAndPort
|
||||
(Option& option, const std::string& hostname, uint16_t port)
|
||||
{
|
||||
option.put(hostOptionName_, hostname);
|
||||
option.put(portOptionName_, util::uitos(port));
|
||||
|
|
|
@ -60,8 +60,13 @@
|
|||
#include "DHTTaskQueue.h"
|
||||
#include "DHTTaskFactory.h"
|
||||
#include "DHTNode.h"
|
||||
#include "DHTSetup.h"
|
||||
#include "DHTRegistry.h"
|
||||
#include "DHTPeerAnnounceStorage.h"
|
||||
#include "DHTTokenTracker.h"
|
||||
#include "DHTMessageDispatcher.h"
|
||||
#include "DHTMessageReceiver.h"
|
||||
#include "DHTMessageFactory.h"
|
||||
#include "DHTMessageCallback.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "BtAnnounce.h"
|
||||
|
@ -102,6 +107,17 @@ PeerInteractionCommand::PeerInteractionCommand
|
|||
setWriteCheckSocket(getSocket());
|
||||
setTimeout(getOption()->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
|
||||
}
|
||||
|
||||
int family;
|
||||
unsigned char compact[COMPACT_LEN_IPV6];
|
||||
int compactlen = bittorrent::packcompact
|
||||
(compact, getPeer()->getIPAddress(), getPeer()->getPort());
|
||||
if(compactlen == COMPACT_LEN_IPV6) {
|
||||
family = AF_INET6;
|
||||
} else {
|
||||
family = AF_INET;
|
||||
}
|
||||
|
||||
SharedHandle<TorrentAttribute> torrentAttrs =
|
||||
bittorrent::getTorrentAttrs(requestGroup_->getDownloadContext());
|
||||
bool metadataGetMode = torrentAttrs->metadata.empty();
|
||||
|
@ -132,10 +148,17 @@ PeerInteractionCommand::PeerInteractionCommand
|
|||
factory->setPeerStorage(peerStorage);
|
||||
factory->setExtensionMessageFactory(extensionMessageFactory);
|
||||
factory->setPeer(getPeer());
|
||||
factory->setLocalNode(DHTRegistry::getData().localNode);
|
||||
factory->setRoutingTable(DHTRegistry::getData().routingTable);
|
||||
factory->setTaskQueue(DHTRegistry::getData().taskQueue);
|
||||
factory->setTaskFactory(DHTRegistry::getData().taskFactory);
|
||||
if(family == AF_INET) {
|
||||
factory->setLocalNode(DHTRegistry::getData().localNode);
|
||||
factory->setRoutingTable(DHTRegistry::getData().routingTable);
|
||||
factory->setTaskQueue(DHTRegistry::getData().taskQueue);
|
||||
factory->setTaskFactory(DHTRegistry::getData().taskFactory);
|
||||
} else {
|
||||
factory->setLocalNode(DHTRegistry::getData6().localNode);
|
||||
factory->setRoutingTable(DHTRegistry::getData6().routingTable);
|
||||
factory->setTaskQueue(DHTRegistry::getData6().taskQueue);
|
||||
factory->setTaskFactory(DHTRegistry::getData6().taskFactory);
|
||||
}
|
||||
if(metadataGetMode) {
|
||||
factory->enableMetadataGetMode();
|
||||
}
|
||||
|
@ -192,10 +215,18 @@ PeerInteractionCommand::PeerInteractionCommand
|
|||
if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) {
|
||||
btInteractive->setUTPexEnabled(true);
|
||||
}
|
||||
if(DHTSetup::initialized()) {
|
||||
btInteractive->setDHTEnabled(true);
|
||||
btInteractive->setLocalNode(DHTRegistry::getData().localNode);
|
||||
factory->setDHTEnabled(true);
|
||||
if(family == AF_INET) {
|
||||
if(DHTRegistry::isInitialized()) {
|
||||
btInteractive->setDHTEnabled(true);
|
||||
factory->setDHTEnabled(true);
|
||||
btInteractive->setLocalNode(DHTRegistry::getData().localNode);
|
||||
}
|
||||
} else {
|
||||
if(DHTRegistry::isInitialized6()) {
|
||||
btInteractive->setDHTEnabled(true);
|
||||
factory->setDHTEnabled(true);
|
||||
btInteractive->setLocalNode(DHTRegistry::getData6().localNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
btInteractive->setUTMetadataRequestFactory(utMetadataRequestFactory);
|
||||
|
|
|
@ -94,6 +94,15 @@
|
|||
# include "BtPostDownloadHandler.h"
|
||||
# include "DHTSetup.h"
|
||||
# include "DHTRegistry.h"
|
||||
# include "DHTNode.h"
|
||||
# include "DHTRoutingTable.h"
|
||||
# include "DHTTaskQueue.h"
|
||||
# include "DHTTaskFactory.h"
|
||||
# include "DHTTokenTracker.h"
|
||||
# include "DHTMessageDispatcher.h"
|
||||
# include "DHTMessageReceiver.h"
|
||||
# include "DHTMessageFactory.h"
|
||||
# include "DHTMessageCallback.h"
|
||||
# include "BtMessageFactory.h"
|
||||
# include "BtRequestFactory.h"
|
||||
# include "BtMessageDispatcher.h"
|
||||
|
@ -283,10 +292,18 @@ void RequestGroup::createInitialCommand
|
|||
SharedHandle<BtProgressInfoFile>
|
||||
(progressInfoFile))));
|
||||
if(metadataGetMode) {
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e);
|
||||
e->addCommand(dhtCommands);
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT) ||
|
||||
option_->getAsBool(PREF_ENABLE_DHT6)) {
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e, AF_INET);
|
||||
e->addCommand(dhtCommands);
|
||||
}
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT6)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e, AF_INET6);
|
||||
e->addCommand(dhtCommands);
|
||||
}
|
||||
} else {
|
||||
logger_->notice("For BitTorrent Magnet URI, enabling DHT is strongly"
|
||||
" recommended. See --enable-dht option.");
|
||||
|
@ -343,16 +360,25 @@ void RequestGroup::createInitialCommand
|
|||
}
|
||||
progressInfoFile_ = progressInfoFile;
|
||||
|
||||
if(!torrentAttrs->privateTorrent && option_->getAsBool(PREF_ENABLE_DHT)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e);
|
||||
e->addCommand(dhtCommands);
|
||||
if(!torrentAttrs->privateTorrent &&
|
||||
(option_->getAsBool(PREF_ENABLE_DHT) ||
|
||||
option_->getAsBool(PREF_ENABLE_DHT6))) {
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e, AF_INET);
|
||||
e->addCommand(dhtCommands);
|
||||
}
|
||||
if(option_->getAsBool(PREF_ENABLE_DHT6)) {
|
||||
std::vector<Command*> dhtCommands;
|
||||
DHTSetup().setup(dhtCommands, e, AF_INET6);
|
||||
e->addCommand(dhtCommands);
|
||||
}
|
||||
const std::vector<std::pair<std::string, uint16_t> >& nodes =
|
||||
torrentAttrs->nodes;
|
||||
if(!nodes.empty() && DHTSetup::initialized()) {
|
||||
std::vector<std::pair<std::string, uint16_t> > entryPoints(nodes);
|
||||
// TODO Are nodes in torrent IPv4 only?
|
||||
if(!nodes.empty() && DHTRegistry::isInitialized()) {
|
||||
DHTEntryPointNameResolveCommand* command =
|
||||
new DHTEntryPointNameResolveCommand(e->newCUID(), e, entryPoints);
|
||||
new DHTEntryPointNameResolveCommand(e->newCUID(), e, nodes);
|
||||
command->setTaskQueue(DHTRegistry::getData().taskQueue);
|
||||
command->setTaskFactory(DHTRegistry::getData().taskFactory);
|
||||
command->setRoutingTable(DHTRegistry::getData().routingTable);
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "TimeA2.h"
|
||||
#include "a2functional.h"
|
||||
#include "LogFactory.h"
|
||||
#include "A2STR.h"
|
||||
#ifdef ENABLE_SSL
|
||||
# include "TLSContext.h"
|
||||
#endif // ENABLE_SSL
|
||||
|
@ -215,6 +216,14 @@ static sock_t bindInternal(int family, int socktype, int protocol,
|
|||
CLOSE(fd);
|
||||
return -1;
|
||||
}
|
||||
if(family == AF_INET6) {
|
||||
int sockopt = 1;
|
||||
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (a2_sockopt_t) &sockopt,
|
||||
sizeof(sockopt)) < 0) {
|
||||
CLOSE(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(::bind(fd, addr, addrlen) == -1) {
|
||||
error = errorMsg();
|
||||
CLOSE(fd);
|
||||
|
@ -258,25 +267,19 @@ void SocketCore::bindWithFamily(uint16_t port, int family, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
void SocketCore::bind(const std::string& addr, uint16_t port, int flags)
|
||||
void SocketCore::bind
|
||||
(const std::string& addr, uint16_t port, int family, int flags)
|
||||
{
|
||||
closeConnection();
|
||||
std::string error;
|
||||
sock_t fd =
|
||||
bindTo(addr.c_str(), port, protocolFamily_, sockType_, flags, error);
|
||||
if(fd == (sock_t)-1) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_SOCKET_BIND, error.c_str()).str());
|
||||
const char* addrp;
|
||||
if(addr.empty()) {
|
||||
addrp = 0;
|
||||
} else {
|
||||
sockfd_ = fd;
|
||||
addrp = addr.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
void SocketCore::bind(uint16_t port, int flags)
|
||||
{
|
||||
closeConnection();
|
||||
std::string error;
|
||||
if(!(flags&AI_PASSIVE) || bindAddrs_.empty()) {
|
||||
sock_t fd = bindTo(0, port, protocolFamily_, sockType_, flags, error);
|
||||
sock_t fd = bindTo(addrp, port, family, sockType_, flags, error);
|
||||
if(fd != (sock_t) -1) {
|
||||
sockfd_ = fd;
|
||||
}
|
||||
|
@ -294,7 +297,11 @@ void SocketCore::bind(uint16_t port, int flags)
|
|||
error = gai_strerror(s);
|
||||
continue;
|
||||
}
|
||||
sock_t fd = bindTo(host, port, protocolFamily_, sockType_, flags, error);
|
||||
if(addrp && strcmp(host, addrp) != 0) {
|
||||
// TODO we should assign something to error?
|
||||
continue;
|
||||
}
|
||||
sock_t fd = bindTo(addrp, port, family, sockType_, flags, error);
|
||||
if(fd != (sock_t)-1) {
|
||||
sockfd_ = fd;
|
||||
break;
|
||||
|
@ -306,6 +313,11 @@ void SocketCore::bind(uint16_t port, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
void SocketCore::bind(uint16_t port, int flags)
|
||||
{
|
||||
bind(A2STR::NIL, port, protocolFamily_, flags);
|
||||
}
|
||||
|
||||
void SocketCore::bind(const struct sockaddr* addr, socklen_t addrlen)
|
||||
{
|
||||
closeConnection();
|
||||
|
|
|
@ -137,8 +137,6 @@ public:
|
|||
|
||||
void bindWithFamily(uint16_t port, int family, int flags = AI_PASSIVE);
|
||||
|
||||
void bind(const std::string& addr, uint16_t port, int flags = AI_PASSIVE);
|
||||
|
||||
/**
|
||||
* Creates a socket and bind it with locahost's address and port.
|
||||
* flags is set to struct addrinfo's ai_flags.
|
||||
|
@ -147,6 +145,9 @@ public:
|
|||
*/
|
||||
void bind(uint16_t port, int flags = AI_PASSIVE);
|
||||
|
||||
void bind
|
||||
(const std::string& addr, uint16_t port, int family, int flags = AI_PASSIVE);
|
||||
|
||||
/**
|
||||
* Listens form connection on it.
|
||||
* Call bind(uint16_t) before calling this function.
|
||||
|
|
|
@ -994,6 +994,17 @@ std::string torrent2Magnet(const SharedHandle<TorrentAttribute>& attrs)
|
|||
return uri;
|
||||
}
|
||||
|
||||
int getCompactLength(int family)
|
||||
{
|
||||
if(family == AF_INET) {
|
||||
return COMPACT_LEN_IPV4;
|
||||
} else if(family == AF_INET6) {
|
||||
return COMPACT_LEN_IPV6;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bittorrent
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -246,6 +246,9 @@ void extractPeer(const ValueBase* peerData, int family, OutputIterator dest)
|
|||
const unsigned char* end = base+length;
|
||||
for(; base != end; base += unit) {
|
||||
std::pair<std::string, uint16_t> p = unpackcompact(base, family_);
|
||||
if(p.first.empty()) {
|
||||
continue;
|
||||
}
|
||||
*dest_++ = SharedHandle<Peer>(new Peer(p.first, p.second));
|
||||
}
|
||||
}
|
||||
|
@ -288,6 +291,8 @@ void extractPeer
|
|||
return extractPeer(peerData.get(), family, dest);
|
||||
}
|
||||
|
||||
int getCompactLength(int family);
|
||||
|
||||
} // namespace bittorrent
|
||||
|
||||
} // namespace aria2
|
||||
|
|
14
src/prefs.cc
14
src/prefs.cc
|
@ -308,6 +308,8 @@ const std::string PREF_PEER_ID_PREFIX("peer-id-prefix");
|
|||
const std::string PREF_ENABLE_PEER_EXCHANGE("enable-peer-exchange");
|
||||
// values: true | false
|
||||
const std::string PREF_ENABLE_DHT("enable-dht");
|
||||
// values: a string
|
||||
const std::string PREF_DHT_LISTEN_ADDR("dht-listen-addr");
|
||||
// values: 1*digit
|
||||
const std::string PREF_DHT_LISTEN_PORT("dht-listen-port");
|
||||
// values: a string
|
||||
|
@ -318,6 +320,18 @@ const std::string PREF_DHT_ENTRY_POINT_PORT("dht-entry-point-port");
|
|||
const std::string PREF_DHT_ENTRY_POINT("dht-entry-point");
|
||||
// values: a string
|
||||
const std::string PREF_DHT_FILE_PATH("dht-file-path");
|
||||
// values: true | false
|
||||
const std::string PREF_ENABLE_DHT6("enable-dht6");
|
||||
// values: a string
|
||||
const std::string PREF_DHT_LISTEN_ADDR6("dht-listen-addr6");
|
||||
// values: a string
|
||||
const std::string PREF_DHT_ENTRY_POINT_HOST6("dht-entry-point-host6");
|
||||
// values: 1*digit
|
||||
const std::string PREF_DHT_ENTRY_POINT_PORT6("dht-entry-point-port6");
|
||||
// values: a string (hostname:port)
|
||||
const std::string PREF_DHT_ENTRY_POINT6("dht-entry-point6");
|
||||
// values: a string
|
||||
const std::string PREF_DHT_FILE_PATH6("dht-file-path6");
|
||||
// values: plain | arc4
|
||||
const std::string PREF_BT_MIN_CRYPTO_LEVEL("bt-min-crypto-level");
|
||||
const std::string V_PLAIN("plain");
|
||||
|
|
14
src/prefs.h
14
src/prefs.h
|
@ -312,6 +312,8 @@ extern const std::string PREF_PEER_ID_PREFIX;
|
|||
extern const std::string PREF_ENABLE_PEER_EXCHANGE;
|
||||
// values: true | false
|
||||
extern const std::string PREF_ENABLE_DHT;
|
||||
// values: a string
|
||||
extern const std::string PREF_DHT_LISTEN_ADDR;
|
||||
// values: 1*digit
|
||||
extern const std::string PREF_DHT_LISTEN_PORT;
|
||||
// values: a string
|
||||
|
@ -322,6 +324,18 @@ extern const std::string PREF_DHT_ENTRY_POINT_PORT;
|
|||
extern const std::string PREF_DHT_ENTRY_POINT;
|
||||
// values: a string
|
||||
extern const std::string PREF_DHT_FILE_PATH;
|
||||
// values: true | false
|
||||
extern const std::string PREF_ENABLE_DHT6;
|
||||
// values: a string
|
||||
extern const std::string PREF_DHT_LISTEN_ADDR6;
|
||||
// values: a string
|
||||
extern const std::string PREF_DHT_ENTRY_POINT_HOST6;
|
||||
// values: 1*digit
|
||||
extern const std::string PREF_DHT_ENTRY_POINT_PORT6;
|
||||
// values: a string (hostname:port)
|
||||
extern const std::string PREF_DHT_ENTRY_POINT6;
|
||||
// values: a string
|
||||
extern const std::string PREF_DHT_FILE_PATH6;
|
||||
// values: plain | arc4
|
||||
extern const std::string PREF_BT_MIN_CRYPTO_LEVEL;
|
||||
extern const std::string V_PLAIN;
|
||||
|
|
|
@ -297,18 +297,18 @@
|
|||
#define TEXT_ENABLE_PEER_EXCHANGE \
|
||||
_(" --enable-peer-exchange[=true|false] Enable Peer Exchange extension.")
|
||||
#define TEXT_ENABLE_DHT \
|
||||
_(" --enable-dht[=true|false] Enable DHT functionality.")
|
||||
_(" --enable-dht[=true|false] Enable IPv4 DHT functionality.")
|
||||
#define TEXT_DHT_LISTEN_PORT \
|
||||
_(" --dht-listen-port=PORT... Set UDP listening port for DHT.\n" \
|
||||
" Multiple ports can be specified by using ',',\n" \
|
||||
" for example: \"6881,6885\". You can also use '-'\n" \
|
||||
" to specify a range: \"6881-6999\". ',' and '-' can\n" \
|
||||
" be used together.")
|
||||
_(" --dht-listen-port=PORT... Set UDP listening port for both IPv4 and IPv6\n" \
|
||||
" DHT. Multiple ports can be specified by using\n" \
|
||||
" ',', for example: \"6881,6885\". You can also\n" \
|
||||
" use '-' to specify a range: \"6881-6999\". ','\n" \
|
||||
" and '-' can be used together.")
|
||||
#define TEXT_DHT_ENTRY_POINT \
|
||||
_(" --dht-entry-point=HOST:PORT Set host and port as an entry point to DHT\n" \
|
||||
_(" --dht-entry-point=HOST:PORT Set host and port as an entry point to IPv4 DHT\n" \
|
||||
" network.")
|
||||
#define TEXT_DHT_FILE_PATH \
|
||||
_(" --dht-file-path=PATH Change the DHT routing table file to PATH.")
|
||||
_(" --dht-file-path=PATH Change the IPv4 DHT routing table file to PATH.")
|
||||
#define TEXT_BT_MIN_CRYPTO_LEVEL \
|
||||
_(" --bt-min-crypto-level=plain|arc4 Set minimum level of encryption method.\n" \
|
||||
" If several encryption methods are provided by a\n" \
|
||||
|
@ -714,3 +714,15 @@
|
|||
_(" --enable-async-dns6[=true|false] Enable IPv6 name resolution in asynchronous\n" \
|
||||
" DNS resolver. This option will be ignored when\n" \
|
||||
" --async-dns=false.")
|
||||
#define TEXT_ENABLE_DHT6 \
|
||||
_(" --enable-dht6[=true|false] Enable IPv6 DHT functionality. See also\n" \
|
||||
" --dht-listen-addr6 option.")
|
||||
#define TEXT_DHT_LISTEN_ADDR6 \
|
||||
_(" --dht-listen-addr6=ADDR Specify address to bind socket for IPv6 DHT. \n" \
|
||||
" It should be a global unicast IPv6 address of the\n" \
|
||||
" host.")
|
||||
#define TEXT_DHT_ENTRY_POINT6 \
|
||||
_(" --dht-entry-point6=HOST:PORT Set host and port as an entry point to IPv6 DHT\n" \
|
||||
" network.")
|
||||
#define TEXT_DHT_FILE_PATH6 \
|
||||
_(" --dht-file-path6=PATH Change the IPv6 DHT routing table file to PATH.")
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "DHTConnectionImpl.h"
|
||||
#include "Exception.h"
|
||||
#include "SocketCore.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "Exception.h"
|
||||
#include "SocketCore.h"
|
||||
#include "A2STR.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class DHTConnectionImplTest:public CppUnit::TestFixture {
|
||||
|
@ -25,13 +28,13 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DHTConnectionImplTest);
|
|||
void DHTConnectionImplTest::testWriteAndReadData()
|
||||
{
|
||||
try {
|
||||
DHTConnectionImpl con1;
|
||||
DHTConnectionImpl con1(AF_INET);
|
||||
uint16_t con1port = 0;
|
||||
CPPUNIT_ASSERT(con1.bind(con1port));
|
||||
CPPUNIT_ASSERT(con1.bind(con1port, A2STR::NIL));
|
||||
|
||||
DHTConnectionImpl con2;
|
||||
DHTConnectionImpl con2(AF_INET);
|
||||
uint16_t con2port = 0;
|
||||
CPPUNIT_ASSERT(con2.bind(con2port));
|
||||
CPPUNIT_ASSERT(con2.bind(con2port, A2STR::NIL));
|
||||
|
||||
std::string message1 = "hello world.";
|
||||
// hostname should be "localhost", not 127.0.0.1. Test failed on Mac OSX10.5
|
||||
|
|
|
@ -15,6 +15,7 @@ class DHTFindNodeReplyMessageTest:public CppUnit::TestFixture {
|
|||
|
||||
CPPUNIT_TEST_SUITE(DHTFindNodeReplyMessageTest);
|
||||
CPPUNIT_TEST(testGetBencodedMessage);
|
||||
CPPUNIT_TEST(testGetBencodedMessage6);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void setUp() {}
|
||||
|
@ -22,6 +23,8 @@ public:
|
|||
void tearDown() {}
|
||||
|
||||
void testGetBencodedMessage();
|
||||
|
||||
void testGetBencodedMessage6();
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,7 +39,7 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
|
|||
util::generateRandomData(tid, DHT_TRANSACTION_ID_LENGTH);
|
||||
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
|
||||
|
||||
DHTFindNodeReplyMessage msg(localNode, remoteNode, transactionID);
|
||||
DHTFindNodeReplyMessage msg(AF_INET, localNode, remoteNode, transactionID);
|
||||
msg.setVersion("A200");
|
||||
std::string compactNodeInfo;
|
||||
SharedHandle<DHTNode> nodes[8];
|
||||
|
@ -46,8 +49,8 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
|
|||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL(COMPACT_LEN_IPV4, bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
|
||||
|
@ -69,4 +72,46 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
|
|||
CPPUNIT_ASSERT_EQUAL(bencode2::encode(&dict), msgbody);
|
||||
}
|
||||
|
||||
void DHTFindNodeReplyMessageTest::testGetBencodedMessage6()
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
SharedHandle<DHTNode> remoteNode(new DHTNode());
|
||||
|
||||
unsigned char tid[DHT_TRANSACTION_ID_LENGTH];
|
||||
util::generateRandomData(tid, DHT_TRANSACTION_ID_LENGTH);
|
||||
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
|
||||
|
||||
DHTFindNodeReplyMessage msg(AF_INET6, localNode, remoteNode, transactionID);
|
||||
msg.setVersion("A200");
|
||||
std::string compactNodeInfo;
|
||||
SharedHandle<DHTNode> nodes[8];
|
||||
for(size_t i = 0; i < DHTBucket::K; ++i) {
|
||||
nodes[i].reset(new DHTNode());
|
||||
nodes[i]->setIPAddress("2001::000"+util::uitos(i+1));
|
||||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL(COMPACT_LEN_IPV6, bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV6]);
|
||||
}
|
||||
msg.setClosestKNodes
|
||||
(std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K]));
|
||||
|
||||
std::string msgbody = msg.getBencodedMessage();
|
||||
|
||||
Dict dict;
|
||||
dict.put("t", transactionID);
|
||||
dict.put("v", "A200");
|
||||
dict.put("y", "r");
|
||||
SharedHandle<Dict> rDict = Dict::g();
|
||||
rDict->put("id", String::g(localNode->getID(), DHT_ID_LENGTH));
|
||||
rDict->put("nodes6", compactNodeInfo);
|
||||
dict.put("r", rDict);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(bencode2::encode(&dict), msgbody);
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -31,24 +31,11 @@ public:
|
|||
|
||||
class MockDHTMessageFactory2:public MockDHTMessageFactory {
|
||||
public:
|
||||
virtual SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessage(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
SharedHandle<MockDHTResponseMessage> m
|
||||
(new MockDHTResponseMessage
|
||||
(localNode_, remoteNode, "get_peers", transactionID));
|
||||
m->peers_ = peers;
|
||||
m->token_ = token;
|
||||
return m;
|
||||
}
|
||||
|
||||
virtual SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<DHTNode> >& closestKNodes,
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
|
@ -56,10 +43,10 @@ public:
|
|||
(new MockDHTResponseMessage
|
||||
(localNode_, remoteNode, "get_peers", transactionID));
|
||||
m->nodes_ = closestKNodes;
|
||||
m->peers_ = peers;
|
||||
m->token_ = token;
|
||||
return m;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -115,14 +102,13 @@ void DHTGetPeersMessageTest::testDoReceivedAction()
|
|||
MockDHTMessageDispatcher dispatcher;
|
||||
MockDHTMessageFactory2 factory;
|
||||
factory.setLocalNode(localNode);
|
||||
DHTRoutingTable routingTable(localNode);
|
||||
|
||||
DHTGetPeersMessage msg(localNode, remoteNode, infoHash, transactionID);
|
||||
msg.setTokenTracker(WeakHandle<DHTTokenTracker>
|
||||
(&tokenTracker));
|
||||
msg.setMessageDispatcher(WeakHandle<DHTMessageDispatcher>
|
||||
(&dispatcher));
|
||||
msg.setMessageFactory(WeakHandle<DHTMessageFactory>
|
||||
(&factory));
|
||||
msg.setRoutingTable(WeakHandle<DHTRoutingTable>(&routingTable));
|
||||
msg.setTokenTracker(WeakHandle<DHTTokenTracker>(&tokenTracker));
|
||||
msg.setMessageDispatcher(WeakHandle<DHTMessageDispatcher>(&dispatcher));
|
||||
msg.setMessageFactory(WeakHandle<DHTMessageFactory>(&factory));
|
||||
{
|
||||
// localhost has peer contact information for that infohash.
|
||||
DHTPeerAnnounceStorage peerAnnounceStorage;
|
||||
|
|
|
@ -16,6 +16,7 @@ class DHTGetPeersReplyMessageTest:public CppUnit::TestFixture {
|
|||
|
||||
CPPUNIT_TEST_SUITE(DHTGetPeersReplyMessageTest);
|
||||
CPPUNIT_TEST(testGetBencodedMessage);
|
||||
CPPUNIT_TEST(testGetBencodedMessage6);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void setUp() {}
|
||||
|
@ -23,6 +24,8 @@ public:
|
|||
void tearDown() {}
|
||||
|
||||
void testGetBencodedMessage();
|
||||
|
||||
void testGetBencodedMessage6();
|
||||
};
|
||||
|
||||
|
||||
|
@ -39,7 +42,8 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
|
|||
|
||||
std::string token = "token";
|
||||
|
||||
DHTGetPeersReplyMessage msg(localNode, remoteNode, token, transactionID);
|
||||
DHTGetPeersReplyMessage msg
|
||||
(AF_INET, localNode, remoteNode, token, transactionID);
|
||||
msg.setVersion("A200");
|
||||
Dict dict;
|
||||
dict.put("t", transactionID);
|
||||
|
@ -58,38 +62,97 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
|
|||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV4,
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
|
||||
}
|
||||
msg.setClosestKNodes
|
||||
(std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K]));
|
||||
|
||||
std::string msgbody = msg.getBencodedMessage();
|
||||
|
||||
rDict->put("nodes", compactNodeInfo);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(util::percentEncode(bencode2::encode(&dict)),
|
||||
util::percentEncode(msgbody));
|
||||
}
|
||||
rDict->removeKey("nodes");
|
||||
{
|
||||
std::vector<SharedHandle<Peer> > peers;
|
||||
SharedHandle<List> valuesList = List::g();
|
||||
for(size_t i = 0; i < 4; ++i) {
|
||||
SharedHandle<Peer> peer(new Peer("192.168.0."+util::uitos(i+1), 6881+i));
|
||||
unsigned char buffer[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact(buffer, peer->getIPAddress(), peer->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV4,
|
||||
bittorrent::packcompact
|
||||
(buffer, peer->getIPAddress(), peer->getPort()));
|
||||
valuesList->append(String::g(buffer, COMPACT_LEN_IPV4));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
msg.setValues(peers);
|
||||
rDict->put("values", valuesList);
|
||||
|
||||
msg.setValues(peers);
|
||||
std::string msgbody = msg.getBencodedMessage();
|
||||
std::string msgbody = msg.getBencodedMessage();
|
||||
CPPUNIT_ASSERT_EQUAL(util::percentEncode(bencode2::encode(&dict)),
|
||||
util::percentEncode(msgbody));
|
||||
}
|
||||
}
|
||||
|
||||
void DHTGetPeersReplyMessageTest::testGetBencodedMessage6()
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
SharedHandle<DHTNode> remoteNode(new DHTNode());
|
||||
|
||||
unsigned char tid[DHT_TRANSACTION_ID_LENGTH];
|
||||
util::generateRandomData(tid, DHT_TRANSACTION_ID_LENGTH);
|
||||
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
|
||||
|
||||
std::string token = "token";
|
||||
|
||||
DHTGetPeersReplyMessage msg
|
||||
(AF_INET6, localNode, remoteNode, token, transactionID);
|
||||
msg.setVersion("A200");
|
||||
Dict dict;
|
||||
dict.put("t", transactionID);
|
||||
dict.put("v", "A200");
|
||||
dict.put("y", "r");
|
||||
SharedHandle<Dict> rDict = Dict::g();
|
||||
rDict->put("id", String::g(localNode->getID(), DHT_ID_LENGTH));
|
||||
rDict->put("token", token);
|
||||
dict.put("r", rDict);
|
||||
{
|
||||
std::string compactNodeInfo;
|
||||
SharedHandle<DHTNode> nodes[8];
|
||||
for(size_t i = 0; i < DHTBucket::K; ++i) {
|
||||
nodes[i].reset(new DHTNode());
|
||||
nodes[i]->setIPAddress("2001::000"+util::uitos(i+1));
|
||||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV6, bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV6]);
|
||||
}
|
||||
msg.setClosestKNodes
|
||||
(std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K]));
|
||||
rDict->put("nodes6", compactNodeInfo);
|
||||
|
||||
std::vector<SharedHandle<Peer> > peers;
|
||||
SharedHandle<List> valuesList = List::g();
|
||||
for(size_t i = 0; i < 4; ++i) {
|
||||
SharedHandle<Peer> peer(new Peer("2001::100"+util::uitos(i+1), 6881+i));
|
||||
unsigned char buffer[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV6,
|
||||
bittorrent::packcompact
|
||||
(buffer, peer->getIPAddress(), peer->getPort()));
|
||||
valuesList->append(String::g(buffer, COMPACT_LEN_IPV6));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
msg.setValues(peers);
|
||||
rDict->put("values", valuesList);
|
||||
|
||||
std::string msgbody = msg.getBencodedMessage();
|
||||
CPPUNIT_ASSERT_EQUAL(util::percentEncode(bencode2::encode(&dict)),
|
||||
util::percentEncode(msgbody));
|
||||
}
|
||||
|
|
|
@ -31,9 +31,10 @@ class DHTMessageFactoryImplTest:public CppUnit::TestFixture {
|
|||
CPPUNIT_TEST(testCreatePingReplyMessage);
|
||||
CPPUNIT_TEST(testCreateFindNodeMessage);
|
||||
CPPUNIT_TEST(testCreateFindNodeReplyMessage);
|
||||
CPPUNIT_TEST(testCreateFindNodeReplyMessage6);
|
||||
CPPUNIT_TEST(testCreateGetPeersMessage);
|
||||
CPPUNIT_TEST(testCreateGetPeersReplyMessage_nodes);
|
||||
CPPUNIT_TEST(testCreateGetPeersReplyMessage_values);
|
||||
CPPUNIT_TEST(testCreateGetPeersReplyMessage);
|
||||
CPPUNIT_TEST(testCreateGetPeersReplyMessage6);
|
||||
CPPUNIT_TEST(testCreateAnnouncePeerMessage);
|
||||
CPPUNIT_TEST(testCreateAnnouncePeerReplyMessage);
|
||||
CPPUNIT_TEST(testReceivedErrorMessage);
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
void setUp()
|
||||
{
|
||||
localNode.reset(new DHTNode());
|
||||
factory.reset(new DHTMessageFactoryImpl());
|
||||
factory.reset(new DHTMessageFactoryImpl(AF_INET));
|
||||
factory->setLocalNode(localNode);
|
||||
memset(transactionID, 0xff, DHT_TRANSACTION_ID_LENGTH);
|
||||
memset(remoteNodeID, 0x0f, DHT_ID_LENGTH);
|
||||
|
@ -66,9 +67,10 @@ public:
|
|||
void testCreatePingReplyMessage();
|
||||
void testCreateFindNodeMessage();
|
||||
void testCreateFindNodeReplyMessage();
|
||||
void testCreateFindNodeReplyMessage6();
|
||||
void testCreateGetPeersMessage();
|
||||
void testCreateGetPeersReplyMessage_nodes();
|
||||
void testCreateGetPeersReplyMessage_values();
|
||||
void testCreateGetPeersReplyMessage();
|
||||
void testCreateGetPeersReplyMessage6();
|
||||
void testCreateAnnouncePeerMessage();
|
||||
void testCreateAnnouncePeerReplyMessage();
|
||||
void testReceivedErrorMessage();
|
||||
|
@ -169,8 +171,10 @@ void DHTMessageFactoryImplTest::testCreateFindNodeReplyMessage()
|
|||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV4,
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
|
||||
|
@ -200,6 +204,58 @@ void DHTMessageFactoryImplTest::testCreateFindNodeReplyMessage()
|
|||
}
|
||||
}
|
||||
|
||||
void DHTMessageFactoryImplTest::testCreateFindNodeReplyMessage6()
|
||||
{
|
||||
factory.reset(new DHTMessageFactoryImpl(AF_INET6));
|
||||
factory->setLocalNode(localNode);
|
||||
factory->setRoutingTable(routingTable);
|
||||
try {
|
||||
Dict dict;
|
||||
dict.put("t", String::g(transactionID, DHT_TRANSACTION_ID_LENGTH));
|
||||
dict.put("y", "r");
|
||||
SharedHandle<Dict> rDict = Dict::g();
|
||||
rDict->put("id", String::g(remoteNodeID, DHT_ID_LENGTH));
|
||||
std::string compactNodeInfo;
|
||||
SharedHandle<DHTNode> nodes[8];
|
||||
for(size_t i = 0; i < DHTBucket::K; ++i) {
|
||||
nodes[i].reset(new DHTNode());
|
||||
nodes[i]->setIPAddress("2001::000"+util::uitos(i+1));
|
||||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV6,
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV6]);
|
||||
}
|
||||
rDict->put("nodes6", compactNodeInfo);
|
||||
dict.put("r", rDict);
|
||||
|
||||
SharedHandle<DHTNode> remoteNode(new DHTNode(remoteNodeID));
|
||||
remoteNode->setIPAddress("2001::2001");
|
||||
remoteNode->setPort(6881);
|
||||
|
||||
SharedHandle<DHTFindNodeReplyMessage> m
|
||||
(dynamic_pointer_cast<DHTFindNodeReplyMessage>
|
||||
(factory->createResponseMessage("find_node", &dict,
|
||||
remoteNode->getIPAddress(),
|
||||
remoteNode->getPort())));
|
||||
|
||||
CPPUNIT_ASSERT(localNode == m->getLocalNode());
|
||||
CPPUNIT_ASSERT(remoteNode == m->getRemoteNode());
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)DHTBucket::K, m->getClosestKNodes().size());
|
||||
CPPUNIT_ASSERT(nodes[0] == m->getClosestKNodes()[0]);
|
||||
CPPUNIT_ASSERT(nodes[7] == m->getClosestKNodes()[7]);
|
||||
CPPUNIT_ASSERT_EQUAL(util::toHex(transactionID, DHT_TRANSACTION_ID_LENGTH),
|
||||
util::toHex(m->getTransactionID()));
|
||||
} catch(Exception& e) {
|
||||
CPPUNIT_FAIL(e.stackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
void DHTMessageFactoryImplTest::testCreateGetPeersMessage()
|
||||
{
|
||||
Dict dict;
|
||||
|
@ -228,7 +284,7 @@ void DHTMessageFactoryImplTest::testCreateGetPeersMessage()
|
|||
util::toHex(m->getInfoHash(), DHT_ID_LENGTH));
|
||||
}
|
||||
|
||||
void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_nodes()
|
||||
void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage()
|
||||
{
|
||||
try {
|
||||
Dict dict;
|
||||
|
@ -244,13 +300,30 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_nodes()
|
|||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV4,
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
|
||||
}
|
||||
rDict->put("nodes", compactNodeInfo);
|
||||
|
||||
std::deque<SharedHandle<Peer> > peers;
|
||||
SharedHandle<List> valuesList = List::g();
|
||||
for(size_t i = 0; i < 4; ++i) {
|
||||
SharedHandle<Peer> peer(new Peer("192.168.0."+util::uitos(i+1), 6881+i));
|
||||
unsigned char buffer[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV4,
|
||||
bittorrent::packcompact
|
||||
(buffer, peer->getIPAddress(), peer->getPort()));
|
||||
valuesList->append(String::g(buffer, COMPACT_LEN_IPV4));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
rDict->put("values", valuesList);
|
||||
|
||||
rDict->put("token", "token");
|
||||
dict.put("r", rDict);
|
||||
|
||||
|
@ -270,6 +343,9 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_nodes()
|
|||
CPPUNIT_ASSERT_EQUAL((size_t)DHTBucket::K, m->getClosestKNodes().size());
|
||||
CPPUNIT_ASSERT(nodes[0] == m->getClosestKNodes()[0]);
|
||||
CPPUNIT_ASSERT(nodes[7] == m->getClosestKNodes()[7]);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)4, m->getValues().size());
|
||||
CPPUNIT_ASSERT(peers[0] == m->getValues()[0]);
|
||||
CPPUNIT_ASSERT(peers[3] == m->getValues()[3]);
|
||||
CPPUNIT_ASSERT_EQUAL(util::toHex(transactionID, DHT_TRANSACTION_ID_LENGTH),
|
||||
util::toHex(m->getTransactionID()));
|
||||
} catch(Exception& e) {
|
||||
|
@ -277,31 +353,54 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_nodes()
|
|||
}
|
||||
}
|
||||
|
||||
void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_values()
|
||||
void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage6()
|
||||
{
|
||||
factory.reset(new DHTMessageFactoryImpl(AF_INET6));
|
||||
factory->setLocalNode(localNode);
|
||||
factory->setRoutingTable(routingTable);
|
||||
try {
|
||||
Dict dict;
|
||||
dict.put("t", String::g(transactionID, DHT_TRANSACTION_ID_LENGTH));
|
||||
dict.put("y", "r");
|
||||
SharedHandle<Dict> rDict = Dict::g();
|
||||
rDict->put("id", String::g(remoteNodeID, DHT_ID_LENGTH));
|
||||
std::string compactNodeInfo;
|
||||
SharedHandle<DHTNode> nodes[8];
|
||||
for(size_t i = 0; i < DHTBucket::K; ++i) {
|
||||
nodes[i].reset(new DHTNode());
|
||||
nodes[i]->setIPAddress("2001::000"+util::uitos(i+1));
|
||||
nodes[i]->setPort(6881+i);
|
||||
|
||||
unsigned char buf[COMPACT_LEN_IPV6];
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV6,
|
||||
bittorrent::packcompact
|
||||
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort()));
|
||||
compactNodeInfo +=
|
||||
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
|
||||
std::string(&buf[0], &buf[COMPACT_LEN_IPV6]);
|
||||
}
|
||||
rDict->put("nodes6", compactNodeInfo);
|
||||
|
||||
std::deque<SharedHandle<Peer> > peers;
|
||||
SharedHandle<List> valuesList = List::g();
|
||||
for(size_t i = 0; i < 4; ++i) {
|
||||
SharedHandle<Peer> peer(new Peer("192.168.0."+util::uitos(i+1), 6881+i));
|
||||
SharedHandle<Peer> peer(new Peer("2001::100"+util::uitos(i+1), 6881+i));
|
||||
unsigned char buffer[COMPACT_LEN_IPV6];
|
||||
bittorrent::packcompact
|
||||
(buffer, peer->getIPAddress(), peer->getPort());
|
||||
valuesList->append(String::g(buffer, COMPACT_LEN_IPV4));
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(COMPACT_LEN_IPV6,
|
||||
bittorrent::packcompact
|
||||
(buffer, peer->getIPAddress(), peer->getPort()));
|
||||
valuesList->append(String::g(buffer, COMPACT_LEN_IPV6));
|
||||
peers.push_back(peer);
|
||||
}
|
||||
rDict->put("values", valuesList);
|
||||
|
||||
rDict->put("token", "token");
|
||||
dict.put("r", rDict);
|
||||
|
||||
SharedHandle<DHTNode> remoteNode(new DHTNode(remoteNodeID));
|
||||
remoteNode->setIPAddress("192.168.0.1");
|
||||
remoteNode->setIPAddress("2001::2001");
|
||||
remoteNode->setPort(6881);
|
||||
|
||||
SharedHandle<DHTGetPeersReplyMessage> m
|
||||
|
@ -313,6 +412,9 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_values()
|
|||
CPPUNIT_ASSERT(localNode == m->getLocalNode());
|
||||
CPPUNIT_ASSERT(remoteNode == m->getRemoteNode());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("token"), m->getToken());
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)DHTBucket::K, m->getClosestKNodes().size());
|
||||
CPPUNIT_ASSERT(nodes[0] == m->getClosestKNodes()[0]);
|
||||
CPPUNIT_ASSERT(nodes[7] == m->getClosestKNodes()[7]);
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)4, m->getValues().size());
|
||||
CPPUNIT_ASSERT(peers[0] == m->getValues()[0]);
|
||||
CPPUNIT_ASSERT(peers[3] == m->getValues()[3]);
|
||||
|
|
|
@ -20,6 +20,7 @@ class DHTRoutingTableDeserializerTest:public CppUnit::TestFixture {
|
|||
|
||||
CPPUNIT_TEST_SUITE(DHTRoutingTableDeserializerTest);
|
||||
CPPUNIT_TEST(testDeserialize);
|
||||
CPPUNIT_TEST(testDeserialize6);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void setUp() {}
|
||||
|
@ -27,6 +28,8 @@ public:
|
|||
void tearDown() {}
|
||||
|
||||
void testDeserialize();
|
||||
|
||||
void testDeserialize6();
|
||||
};
|
||||
|
||||
|
||||
|
@ -45,14 +48,14 @@ void DHTRoutingTableDeserializerTest::testDeserialize()
|
|||
nodesSrc[1]->setIPAddress("non-numerical-name");
|
||||
std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
|
||||
|
||||
DHTRoutingTableSerializer s;
|
||||
DHTRoutingTableSerializer s(AF_INET);
|
||||
s.setLocalNode(localNode);
|
||||
s.setNodes(nodes);
|
||||
|
||||
std::stringstream ss;
|
||||
s.serialize(ss);
|
||||
|
||||
DHTRoutingTableDeserializer d;
|
||||
DHTRoutingTableDeserializer d(AF_INET);
|
||||
d.deserialize(ss);
|
||||
|
||||
CPPUNIT_ASSERT(memcmp(localNode->getID(), d.getLocalNode()->getID(),
|
||||
|
@ -70,4 +73,44 @@ void DHTRoutingTableDeserializerTest::testDeserialize()
|
|||
CPPUNIT_ASSERT(memcmp(nodes[2]->getID(), dsnodes[1]->getID(), DHT_ID_LENGTH) == 0);
|
||||
}
|
||||
|
||||
void DHTRoutingTableDeserializerTest::testDeserialize6()
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
|
||||
SharedHandle<DHTNode> nodesSrc[3];
|
||||
for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
|
||||
nodesSrc[i].reset(new DHTNode());
|
||||
nodesSrc[i]->setIPAddress("2001::100"+util::uitos(i+1));
|
||||
nodesSrc[i]->setPort(6881+i);
|
||||
}
|
||||
nodesSrc[1]->setIPAddress("non-numerical-name");
|
||||
std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
|
||||
|
||||
DHTRoutingTableSerializer s(AF_INET6);
|
||||
s.setLocalNode(localNode);
|
||||
s.setNodes(nodes);
|
||||
|
||||
std::stringstream ss;
|
||||
s.serialize(ss);
|
||||
|
||||
DHTRoutingTableDeserializer d(AF_INET6);
|
||||
d.deserialize(ss);
|
||||
|
||||
CPPUNIT_ASSERT(memcmp(localNode->getID(), d.getLocalNode()->getID(),
|
||||
DHT_ID_LENGTH) == 0);
|
||||
|
||||
std::cout << d.getSerializedTime().getTime() << std::endl;
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)2, d.getNodes().size());
|
||||
const std::vector<SharedHandle<DHTNode> >& dsnodes = d.getNodes();
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("2001::1001"), dsnodes[0]->getIPAddress());
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, dsnodes[0]->getPort());
|
||||
CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), dsnodes[0]->getID(),
|
||||
DHT_ID_LENGTH) == 0);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("2001::1003"), dsnodes[1]->getIPAddress());
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6883, dsnodes[1]->getPort());
|
||||
CPPUNIT_ASSERT(memcmp(nodes[2]->getID(), dsnodes[1]->getID(),
|
||||
DHT_ID_LENGTH) == 0);
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -20,42 +20,35 @@ class DHTRoutingTableSerializerTest:public CppUnit::TestFixture {
|
|||
|
||||
CPPUNIT_TEST_SUITE(DHTRoutingTableSerializerTest);
|
||||
CPPUNIT_TEST(testSerialize);
|
||||
CPPUNIT_TEST(testSerialize6);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
private:
|
||||
char zero[256];
|
||||
char buf[20];
|
||||
|
||||
void checkToLocalnode
|
||||
(std::istream& ss, const SharedHandle<DHTNode>& localNode);
|
||||
|
||||
void checkNumNodes(std::istream& ss, size_t expected);
|
||||
public:
|
||||
void setUp() {}
|
||||
void setUp()
|
||||
{
|
||||
memset(zero, 0, sizeof(zero));
|
||||
}
|
||||
|
||||
void tearDown() {}
|
||||
|
||||
void testSerialize();
|
||||
|
||||
void testSerialize6();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(DHTRoutingTableSerializerTest);
|
||||
|
||||
void DHTRoutingTableSerializerTest::testSerialize()
|
||||
void DHTRoutingTableSerializerTest::checkToLocalnode
|
||||
(std::istream& ss, const SharedHandle<DHTNode>& localNode)
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
|
||||
SharedHandle<DHTNode> nodesSrc[3];
|
||||
for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
|
||||
nodesSrc[i].reset(new DHTNode());
|
||||
nodesSrc[i]->setIPAddress("192.168.0."+util::uitos(i+1));
|
||||
nodesSrc[i]->setPort(6881+i);
|
||||
}
|
||||
nodesSrc[1]->setIPAddress("non-numerical-name");
|
||||
std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
|
||||
|
||||
DHTRoutingTableSerializer s;
|
||||
s.setLocalNode(localNode);
|
||||
s.setNodes(nodes);
|
||||
|
||||
std::stringstream ss;
|
||||
s.serialize(ss);
|
||||
|
||||
char zero[16];
|
||||
memset(zero, 0, sizeof(zero));
|
||||
|
||||
char buf[20];
|
||||
// header
|
||||
ss.read(buf, 8);
|
||||
// magic
|
||||
|
@ -89,14 +82,44 @@ void DHTRoutingTableSerializerTest::testSerialize()
|
|||
// 4bytes reserved
|
||||
ss.read(buf, 4);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
|
||||
}
|
||||
|
||||
void DHTRoutingTableSerializerTest::checkNumNodes
|
||||
(std::istream& ss, size_t expected)
|
||||
{
|
||||
// number of nodes saved
|
||||
ss.read(buf, 4);
|
||||
uint32_t numNodes;
|
||||
memcpy(&numNodes, buf, sizeof(numNodes));
|
||||
numNodes = ntohl(numNodes);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL((uint32_t)3, numNodes);
|
||||
CPPUNIT_ASSERT_EQUAL((uint32_t)expected, numNodes);
|
||||
}
|
||||
|
||||
void DHTRoutingTableSerializerTest::testSerialize()
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
|
||||
SharedHandle<DHTNode> nodesSrc[3];
|
||||
for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
|
||||
nodesSrc[i].reset(new DHTNode());
|
||||
nodesSrc[i]->setIPAddress("192.168.0."+util::uitos(i+1));
|
||||
nodesSrc[i]->setPort(6881+i);
|
||||
}
|
||||
nodesSrc[1]->setIPAddress("non-numerical-name");
|
||||
std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
|
||||
|
||||
DHTRoutingTableSerializer s(AF_INET);
|
||||
s.setLocalNode(localNode);
|
||||
s.setNodes(nodes);
|
||||
|
||||
std::stringstream ss;
|
||||
s.serialize(ss);
|
||||
|
||||
checkToLocalnode(ss, localNode);
|
||||
size_t numNodes = 3;
|
||||
checkNumNodes(ss, numNodes);
|
||||
|
||||
// 4bytes reserved
|
||||
ss.read(buf, 4);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
|
||||
|
@ -199,4 +222,92 @@ void DHTRoutingTableSerializerTest::testSerialize()
|
|||
CPPUNIT_ASSERT(ss.eof());
|
||||
}
|
||||
|
||||
void DHTRoutingTableSerializerTest::testSerialize6()
|
||||
{
|
||||
SharedHandle<DHTNode> localNode(new DHTNode());
|
||||
|
||||
SharedHandle<DHTNode> nodesSrc[2];
|
||||
for(size_t i = 0; i < A2_ARRAY_LEN(nodesSrc); ++i) {
|
||||
nodesSrc[i].reset(new DHTNode());
|
||||
nodesSrc[i]->setIPAddress("2001::100"+util::uitos(i+1));
|
||||
nodesSrc[i]->setPort(6881+i);
|
||||
}
|
||||
nodesSrc[1]->setIPAddress("non-numerical-name");
|
||||
std::vector<SharedHandle<DHTNode> > nodes(vbegin(nodesSrc), vend(nodesSrc));
|
||||
|
||||
DHTRoutingTableSerializer s(AF_INET6);
|
||||
s.setLocalNode(localNode);
|
||||
s.setNodes(nodes);
|
||||
|
||||
std::stringstream ss;
|
||||
s.serialize(ss);
|
||||
|
||||
checkToLocalnode(ss, localNode);
|
||||
size_t numNodes = 2;
|
||||
checkNumNodes(ss, numNodes);
|
||||
|
||||
// 4bytes reserved
|
||||
ss.read(buf, 4);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
|
||||
|
||||
// node[0]
|
||||
// 1byte compatc peer format length
|
||||
{
|
||||
uint8_t len;
|
||||
ss >> len;
|
||||
CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
|
||||
}
|
||||
// 7bytes reserved
|
||||
ss.read(buf, 7);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
|
||||
// 18 bytes compact peer info
|
||||
ss.read(buf, 18);
|
||||
{
|
||||
std::pair<std::string, uint16_t> peer =
|
||||
bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
|
||||
AF_INET6);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("2001::1001"), peer.first);
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
|
||||
}
|
||||
// 6bytes reserved
|
||||
ss.read(buf, 6);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
|
||||
// localnode ID
|
||||
ss.read(buf, DHT_ID_LENGTH);
|
||||
CPPUNIT_ASSERT(memcmp(nodes[0]->getID(), buf, DHT_ID_LENGTH) == 0);
|
||||
// 4bytes reserved
|
||||
ss.read(buf, 4);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
|
||||
|
||||
// node[1]
|
||||
// 1byte compatc peer format length
|
||||
{
|
||||
uint8_t len;
|
||||
ss >> len;
|
||||
CPPUNIT_ASSERT_EQUAL((uint8_t)18, len);
|
||||
}
|
||||
// 7bytes reserved
|
||||
ss.read(buf, 7);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 7) == 0);
|
||||
// 18bytes compact peer info
|
||||
ss.read(buf, 18);
|
||||
// zero filled because node[1]'s hostname is not numerical form
|
||||
// deserializer should skip this entry
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 18) == 0);
|
||||
// 6bytes reserved
|
||||
ss.read(buf, 6);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 6) == 0);
|
||||
// localnode ID
|
||||
ss.read(buf, DHT_ID_LENGTH);
|
||||
CPPUNIT_ASSERT(memcmp(nodes[1]->getID(), buf, DHT_ID_LENGTH) == 0);
|
||||
// 4bytes reserved
|
||||
ss.read(buf, 4);
|
||||
CPPUNIT_ASSERT(memcmp(zero, buf, 4) == 0);
|
||||
|
||||
// check to see stream ends
|
||||
ss.read(buf, 1);
|
||||
CPPUNIT_ASSERT_EQUAL((std::streamsize)0, ss.gcount());
|
||||
CPPUNIT_ASSERT(ss.eof());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -46,7 +46,7 @@ void LpdMessageDispatcherTest::testSendMessage()
|
|||
#ifdef __MINGW32__
|
||||
recvsock->bindWithFamily(LPD_MULTICAST_PORT, AF_INET);
|
||||
#else // !__MINGW32__
|
||||
recvsock->bind(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
recvsock->bind(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT, AF_INET);
|
||||
#endif // !__MINGW32__
|
||||
recvsock->joinMulticastGroup(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT, "");
|
||||
|
||||
|
|
|
@ -81,18 +81,9 @@ public:
|
|||
createGetPeersReplyMessage
|
||||
(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<DHTNode> >& closestKNodes,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
return SharedHandle<DHTResponseMessage>();
|
||||
}
|
||||
|
||||
|
||||
virtual SharedHandle<DHTResponseMessage>
|
||||
createGetPeersReplyMessage(const SharedHandle<DHTNode>& remoteNode,
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
const std::vector<SharedHandle<Peer> >& peers,
|
||||
const std::string& token,
|
||||
const std::string& transactionID)
|
||||
{
|
||||
return SharedHandle<DHTResponseMessage>();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue