2010-08-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added bittorrent::packcompact() which replaces
	bittorrent::createcompact() and supports IPv6 addresses. Rewritten
	bittorrent::unpackcompact() and bittorrent::extractPeer() to
	support IPv6 addresses. Fixed added.f flags in ut_pex.
	* src/BtConstants.h
	* src/DHTFindNodeReplyMessage.cc
	* src/DHTGetPeersReplyMessage.cc
	* src/DHTMessageFactoryImpl.cc
	* src/DHTRoutingTableDeserializer.cc
	* src/DHTRoutingTableSerializer.cc
	* src/DHTTokenTracker.cc
	* src/DefaultBtAnnounce.cc
	* src/UTPexExtensionMessage.cc
	* src/bittorrent_helper.cc
	* src/bittorrent_helper.h
	* test/BittorrentHelperTest.cc
	* test/DHTFindNodeReplyMessageTest.cc
	* test/DHTGetPeersReplyMessageTest.cc
	* test/DHTMessageFactoryImplTest.cc
	* test/DHTRoutingTableSerializerTest.cc
	* test/DefaultExtensionMessageFactoryTest.cc
	* test/UTPexExtensionMessageTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-08-03 11:44:24 +00:00
parent 939a372727
commit 2bd5020f81
19 changed files with 275 additions and 162 deletions

View File

@ -1,3 +1,28 @@
2010-08-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added bittorrent::packcompact() which replaces
bittorrent::createcompact() and supports IPv6 addresses. Rewritten
bittorrent::unpackcompact() and bittorrent::extractPeer() to
support IPv6 addresses. Fixed added.f flags in ut_pex.
* src/BtConstants.h
* src/DHTFindNodeReplyMessage.cc
* src/DHTGetPeersReplyMessage.cc
* src/DHTMessageFactoryImpl.cc
* src/DHTRoutingTableDeserializer.cc
* src/DHTRoutingTableSerializer.cc
* src/DHTTokenTracker.cc
* src/DefaultBtAnnounce.cc
* src/UTPexExtensionMessage.cc
* src/bittorrent_helper.cc
* src/bittorrent_helper.h
* test/BittorrentHelperTest.cc
* test/DHTFindNodeReplyMessageTest.cc
* test/DHTGetPeersReplyMessageTest.cc
* test/DHTMessageFactoryImplTest.cc
* test/DHTRoutingTableSerializerTest.cc
* test/DefaultExtensionMessageFactoryTest.cc
* test/UTPexExtensionMessageTest.cc
2010-08-01 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2010-08-01 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --enable-async-dns6 option. This option enables IPv6 name Added --enable-async-dns6 option. This option enables IPv6 name

View File

@ -62,4 +62,8 @@ typedef std::map<std::string, uint8_t> Extensions;
#define LPD_MULTICAST_PORT 6771 #define LPD_MULTICAST_PORT 6771
#define COMPACT_LEN_IPV4 6
#define COMPACT_LEN_IPV6 18
#endif // _D_BT_CONSTANTS_ #endif // _D_BT_CONSTANTS_

View File

@ -81,8 +81,11 @@ SharedHandle<Dict> DHTFindNodeReplyMessage::getResponse()
i != eoi && offset < DHTBucket::K*26; ++i) { i != eoi && offset < DHTBucket::K*26; ++i) {
SharedHandle<DHTNode> node = *i; SharedHandle<DHTNode> node = *i;
memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH); memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
if(bittorrent::createcompact(buffer+20+offset, node->getIPAddress(), unsigned char compact[COMPACT_LEN_IPV6];
node->getPort())) { int compactlen = bittorrent::packcompact
(compact, node->getIPAddress(), node->getPort());
if(compactlen == COMPACT_LEN_IPV4) {
memcpy(buffer+20+offset, compact, compactlen);
offset += 26; offset += 26;
} }
} }

View File

@ -85,8 +85,11 @@ SharedHandle<Dict> DHTGetPeersReplyMessage::getResponse()
i != eoi && offset < DHTBucket::K*26; ++i) { i != eoi && offset < DHTBucket::K*26; ++i) {
SharedHandle<DHTNode> node = *i; SharedHandle<DHTNode> node = *i;
memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH); memcpy(buffer+offset, node->getID(), DHT_ID_LENGTH);
if(bittorrent::createcompact unsigned char compact[COMPACT_LEN_IPV6];
(buffer+20+offset, node->getIPAddress(), node->getPort())) { int compactlen = bittorrent::packcompact
(compact, node->getIPAddress(), node->getPort());
if(compactlen == COMPACT_LEN_IPV4) {
memcpy(buffer+20+offset, compact, compactlen);
offset += 26; offset += 26;
} }
} }
@ -117,10 +120,11 @@ SharedHandle<Dict> DHTGetPeersReplyMessage::getResponse()
eoi = values_.end(); i != eoi && valuesList->size() < MAX_VALUES_SIZE; eoi = values_.end(); i != eoi && valuesList->size() < MAX_VALUES_SIZE;
++i) { ++i) {
const SharedHandle<Peer>& peer = *i; const SharedHandle<Peer>& peer = *i;
unsigned char buffer[6]; unsigned char compact[COMPACT_LEN_IPV6];
if(bittorrent::createcompact int compactlen = bittorrent::packcompact
(buffer, peer->getIPAddress(), peer->getPort())) { (compact, peer->getIPAddress(), peer->getPort());
valuesList->append(String::g(buffer, sizeof(buffer))); if(compactlen == COMPACT_LEN_IPV4) {
valuesList->append(String::g(compact, compactlen));
} }
} }
rDict->put(VALUES, valuesList); rDict->put(VALUES, valuesList);

View File

@ -365,7 +365,7 @@ DHTMessageFactoryImpl::extractNodes(const unsigned char* src, size_t length)
for(size_t offset = 0; offset < length; offset += 26) { for(size_t offset = 0; offset < length; offset += 26) {
SharedHandle<DHTNode> node(new DHTNode(src+offset)); SharedHandle<DHTNode> node(new DHTNode(src+offset));
std::pair<std::string, uint16_t> addr = std::pair<std::string, uint16_t> addr =
bittorrent::unpackcompact(src+offset+DHT_ID_LENGTH); bittorrent::unpackcompact(src+offset+DHT_ID_LENGTH, AF_INET);
if(addr.first.empty()) { if(addr.first.empty()) {
continue; continue;
} }
@ -448,7 +448,7 @@ DHTMessageFactoryImpl::createGetPeersReplyMessageWithValues
const String* data = asString(*i); const String* data = asString(*i);
if(data && data->s().size() == 6) { if(data && data->s().size() == 6) {
std::pair<std::string, uint16_t> addr = std::pair<std::string, uint16_t> addr =
bittorrent::unpackcompact(data->uc()); bittorrent::unpackcompact(data->uc(), AF_INET);
SharedHandle<Peer> peer(new Peer(addr.first, addr.second)); SharedHandle<Peer> peer(new Peer(addr.first, addr.second));
peers.push_back(peer); peers.push_back(peer);
} }

View File

@ -182,7 +182,9 @@ void DHTRoutingTableDeserializer::deserialize(std::istream& in)
CHECK_STREAM(in, 42); CHECK_STREAM(in, 42);
continue; continue;
} }
std::pair<std::string, uint16_t> peer = bittorrent::unpackcompact(buf); // TODO DHT6 protocol family should be configurable.
std::pair<std::string, uint16_t> peer =
bittorrent::unpackcompact(buf, AF_INET);
if(peer.first.empty()) { if(peer.first.empty()) {
// skip this entry // skip this entry
readBytes(buf, buf.size(), in, 42); readBytes(buf, buf.size(), in, 42);

View File

@ -105,19 +105,21 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o)
for(std::vector<SharedHandle<DHTNode> >::const_iterator i = nodes_.begin(), for(std::vector<SharedHandle<DHTNode> >::const_iterator i = nodes_.begin(),
eoi = nodes_.end(); i != eoi; ++i) { eoi = nodes_.end(); i != eoi; ++i) {
const SharedHandle<DHTNode>& node = *i; const SharedHandle<DHTNode>& node = *i;
// Currently, only IPv4 address and IPv4-mapped address are saved. // Currently, only IPv4 addresses are saved.
// 6bytes: write IP address + port in Compact IP-address/port info form. // 6bytes: write IP address + port in Compact IP-address/port info form.
unsigned char compactPeer[6]; unsigned char compactPeer[COMPACT_LEN_IPV6];
if(!bittorrent::createcompact int compactlen = bittorrent::packcompact
(compactPeer, node->getIPAddress(), node->getPort())) { (compactPeer, node->getIPAddress(), node->getPort());
memset(compactPeer, 0, 6); if(compactlen != COMPACT_LEN_IPV4) {
compactlen = COMPACT_LEN_IPV4;
memset(compactPeer, 0, COMPACT_LEN_IPV4);
} }
// 1byte compact peer format length // 1byte compact peer format length
o << static_cast<uint8_t>(sizeof(compactPeer)); o << static_cast<uint8_t>(compactlen);
// 7bytes reserved // 7bytes reserved
o.write(zero, 7); o.write(zero, 7);
// 6 bytes compact peer // 6 bytes compact peer
o.write(reinterpret_cast<const char*>(compactPeer), 6); o.write(reinterpret_cast<const char*>(compactPeer), compactlen);
// 2bytes reserved // 2bytes reserved
o.write(zero, 2); o.write(zero, 2);
// 16bytes reserved // 16bytes reserved

View File

@ -59,20 +59,24 @@ DHTTokenTracker::DHTTokenTracker(const unsigned char* initialSecret)
DHTTokenTracker::~DHTTokenTracker() {} DHTTokenTracker::~DHTTokenTracker() {}
std::string DHTTokenTracker::generateToken(const unsigned char* infoHash, std::string DHTTokenTracker::generateToken
const std::string& ipaddr, uint16_t port, (const unsigned char* infoHash,
const unsigned char* secret) const const std::string& ipaddr, uint16_t port,
const unsigned char* secret) const
{ {
unsigned char src[DHT_ID_LENGTH+6+SECRET_SIZE]; unsigned char src[DHT_ID_LENGTH+COMPACT_LEN_IPV6+SECRET_SIZE];
if(!bittorrent::createcompact(src+DHT_ID_LENGTH, ipaddr, port)) { memset(src, 0, sizeof(src));
int compactlen = bittorrent::packcompact(src+DHT_ID_LENGTH, ipaddr, port);
if(compactlen == 0) {
throw DL_ABORT_EX throw DL_ABORT_EX
(StringFormat("Token generation failed: ipaddr=%s, port=%u", (StringFormat("Token generation failed: ipaddr=%s, port=%u",
ipaddr.c_str(), port).str()); ipaddr.c_str(), port).str());
} }
memcpy(src, infoHash, DHT_ID_LENGTH); memcpy(src, infoHash, DHT_ID_LENGTH);
memcpy(src+DHT_ID_LENGTH+6, secret, SECRET_SIZE); memcpy(src+DHT_ID_LENGTH+COMPACT_LEN_IPV6, secret, SECRET_SIZE);
unsigned char md[20]; unsigned char md[20];
MessageDigestHelper::digest(md, sizeof(md), MessageDigestContext::SHA1, src, sizeof(src)); MessageDigestHelper::digest(md, sizeof(md), MessageDigestContext::SHA1,
src, sizeof(src));
return std::string(&md[0], &md[sizeof(md)]); return std::string(&md[0], &md[sizeof(md)]);
} }

View File

@ -276,7 +276,7 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse,
} else { } else {
if(!btRuntime_->isHalt() && btRuntime_->lessThanMinPeers()) { if(!btRuntime_->isHalt() && btRuntime_->lessThanMinPeers()) {
std::vector<SharedHandle<Peer> > peers; std::vector<SharedHandle<Peer> > peers;
bittorrent::extractPeer(peerData, std::back_inserter(peers)); bittorrent::extractPeer(peerData, AF_INET, std::back_inserter(peers));
peerStorage_->addPeer(peers); peerStorage_->addPeer(peers);
} }
} }

View File

@ -78,11 +78,12 @@ UTPexExtensionMessage::createCompactPeerListAndFlag
std::string flagstring; std::string flagstring;
for(std::vector<SharedHandle<Peer> >::const_iterator itr = peers.begin(), for(std::vector<SharedHandle<Peer> >::const_iterator itr = peers.begin(),
eoi = peers.end(); itr != eoi; ++itr) { eoi = peers.end(); itr != eoi; ++itr) {
unsigned char compact[6]; unsigned char compact[COMPACT_LEN_IPV6];
if(bittorrent::createcompact int compactlen = bittorrent::packcompact
(compact, (*itr)->getIPAddress(), (*itr)->getPort())) { (compact, (*itr)->getIPAddress(), (*itr)->getPort());
addrstring.append(&compact[0], &compact[6]); if(compactlen == COMPACT_LEN_IPV4) {
flagstring += (*itr)->isSeeder() ? "2" : "0"; addrstring.append(&compact[0], &compact[compactlen]);
flagstring += (*itr)->isSeeder() ? 0x02 : 0x00;
} }
} }
return std::pair<std::string, std::string>(addrstring, flagstring); return std::pair<std::string, std::string>(addrstring, flagstring);
@ -162,11 +163,13 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len)
if(dict) { if(dict) {
const String* added = asString(dict->get("added")); const String* added = asString(dict->get("added"));
if(added) { if(added) {
bittorrent::extractPeer(added, std::back_inserter(msg->freshPeers_)); bittorrent::extractPeer
(added, AF_INET, std::back_inserter(msg->freshPeers_));
} }
const String* dropped = asString(dict->get("dropped")); const String* dropped = asString(dict->get("dropped"));
if(dropped) { if(dropped) {
bittorrent::extractPeer(dropped, std::back_inserter(msg->droppedPeers_)); bittorrent::extractPeer
(dropped, AF_INET, std::back_inserter(msg->droppedPeers_));
} }
} }
return msg; return msg;

View File

@ -54,6 +54,7 @@
#include "magnet.h" #include "magnet.h"
#include "bencode2.h" #include "bencode2.h"
#include "TorrentAttribute.h" #include "TorrentAttribute.h"
#include "SocketCore.h"
namespace aria2 { namespace aria2 {
@ -623,8 +624,9 @@ void computeFastSet
(std::vector<size_t>& fastSet, const std::string& ipaddr, (std::vector<size_t>& fastSet, const std::string& ipaddr,
size_t numPieces, const unsigned char* infoHash, size_t fastSetSize) size_t numPieces, const unsigned char* infoHash, size_t fastSetSize)
{ {
unsigned char compact[6]; unsigned char compact[COMPACT_LEN_IPV6];
if(!createcompact(compact, ipaddr, 0)) { int compactlen = packcompact(compact, ipaddr, 0);
if(compactlen != COMPACT_LEN_IPV4) {
return; return;
} }
if(numPieces < fastSetSize) { if(numPieces < fastSetSize) {
@ -801,51 +803,51 @@ void createPeerMessageString
msg[4] = messageId; msg[4] = messageId;
} }
bool createcompact int packcompact
(unsigned char* compact, const std::string& addr, uint16_t port) (unsigned char* compact, const std::string& addr, uint16_t port)
{ {
struct addrinfo hints;
struct addrinfo* res; struct addrinfo* res;
memset(&hints, 0, sizeof(hints)); int s =
hints.ai_family = AF_INET; // since compact peer format is ipv4 only. callGetaddrinfo(&res, addr.c_str(), 0, AF_UNSPEC, 0, AI_NUMERICHOST, 0);
hints.ai_flags = AI_NUMERICHOST; if(s != 0) {
if(getaddrinfo(addr.c_str(), 0, &hints, &res)) { return 0;
return false;
} }
struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(res->ai_addr); WSAAPI_AUTO_DELETE<struct addrinfo*> resDeleter(res, freeaddrinfo);
memcpy(compact, &(in->sin_addr.s_addr), sizeof(uint32_t)); uint16_t portN = htons(port);
uint16_t port_nworder(htons(port)); for(struct addrinfo* rp = res; rp; rp = rp->ai_next) {
memcpy(compact+4, &port_nworder, sizeof(uint16_t)); if(rp->ai_family == AF_INET) {
freeaddrinfo(res); struct sockaddr_in* in =
return true; reinterpret_cast<struct sockaddr_in*>(res->ai_addr);
memcpy(compact, &(in->sin_addr), 4);
memcpy(compact+4, &portN, sizeof(portN));
return COMPACT_LEN_IPV4;
} else if(rp->ai_family == AF_INET6) {
struct sockaddr_in6* in6 =
reinterpret_cast<struct sockaddr_in6*>(res->ai_addr);
memcpy(compact, &(in6->sin6_addr), 16);
memcpy(compact+16, &portN, sizeof(portN));
return COMPACT_LEN_IPV6;
}
}
return 0;
} }
std::pair<std::string, uint16_t> unpackcompact(const unsigned char* compact) std::pair<std::string, uint16_t> unpackcompact
(const unsigned char* compact, int family)
{ {
struct sockaddr_in in; int portOffset = family == AF_INET?4:16;
memset(&in, 0, sizeof(in)); std::pair<std::string, uint16_t> r;
#ifdef HAVE_SOCKADDR_IN_SIN_LEN char buf[INET6_ADDRSTRLEN];
// For netbsd if(!inet_ntop(family, compact, buf, sizeof(buf))) {
in.sin_len = sizeof(in); return r;
#endif // HAVE_SOCKADDR_IN_SIN_LEN
in.sin_family = AF_INET;
memcpy(&(in.sin_addr.s_addr), compact, sizeof(uint32_t));
in.sin_port = 0;
char host[NI_MAXHOST];
int s;
s = getnameinfo(reinterpret_cast<const struct sockaddr*>(&in), sizeof(in),
host, NI_MAXHOST, 0, 0,
NI_NUMERICHOST);
if(s) {
return std::pair<std::string, uint16_t>();
} }
uint16_t port_nworder; r.first = buf;
memcpy(&port_nworder, compact+sizeof(uint32_t), sizeof(uint16_t)); uint16_t portN;
uint16_t port = ntohs(port_nworder); memcpy(&portN, compact+portOffset, sizeof(portN));
return std::make_pair(host, port); r.second = ntohs(portN);
return r;
} }
void assertPayloadLengthGreater void assertPayloadLengthGreater
(size_t threshold, size_t actual, const std::string& msgName) (size_t threshold, size_t actual, const std::string& msgName)
{ {

View File

@ -182,18 +182,25 @@ void createPeerMessageString
(unsigned char* msg, size_t msgLength, size_t payloadLength, uint8_t messageId); (unsigned char* msg, size_t msgLength, size_t payloadLength, uint8_t messageId);
/** /**
* Creates compact tracker format(6bytes for ipv4 address and port) * Creates compact form(packed addresss + 2bytes port) and stores the
* and stores the results in compact. * results in compact. This function looks addr and if it is IPv4
* compact must be at least 6 bytes and pre-allocated. * address, it stores 6bytes in compact and if it is IPv6, it stores
* Returns true if creation is successful, otherwise returns false. * 18bytes in compact. So compact must be at least 18 bytes and
* The example of failure reason is that addr is not numbers-and-dots * pre-allocated. Returns the number of written bytes; for IPv4
* notation. * address, it is 6 and for IPv6, it is 18. On failure, returns 0.
*/ */
bool createcompact int packcompact
(unsigned char* compact, const std::string& addr, uint16_t port); (unsigned char* compact, const std::string& addr, uint16_t port);
// Unpack compact into pair of IPv4 address and port. /**
std::pair<std::string, uint16_t> unpackcompact(const unsigned char* compact); * Unpack packed address and port in compact and returns address and
* port pair. family must be AF_INET or AF_INET6. If family is
* AF_INET, first 6 bytes from compact is used. If family is
* AF_INET6, first 18 bytes from compact is used. On failure, returns
* std::pair<std::string, uint16_t>().
*/
std::pair<std::string, uint16_t>
unpackcompact(const unsigned char* compact, int family);
// Throws exception if threshold >= actual // Throws exception if threshold >= actual
void assertPayloadLengthGreater void assertPayloadLengthGreater
@ -216,30 +223,30 @@ std::string metadata2Torrent
std::string torrent2Magnet(const SharedHandle<TorrentAttribute>& attrs); std::string torrent2Magnet(const SharedHandle<TorrentAttribute>& attrs);
template<typename OutputIterator> template<typename OutputIterator>
void extractPeer(const ValueBase* peerData, OutputIterator dest) void extractPeer(const ValueBase* peerData, int family, OutputIterator dest)
{ {
class PeerListValueBaseVisitor:public ValueBaseVisitor { class PeerListValueBaseVisitor:public ValueBaseVisitor {
private: private:
OutputIterator dest_; OutputIterator dest_;
int family_;
public: public:
PeerListValueBaseVisitor(OutputIterator dest):dest_(dest) {} PeerListValueBaseVisitor(OutputIterator dest, int family):
dest_(dest),
family_(family) {}
virtual ~PeerListValueBaseVisitor() {} virtual ~PeerListValueBaseVisitor() {}
virtual void visit(const String& peerData) virtual void visit(const String& peerData)
{ {
int unit = family_ == AF_INET?6:18;
size_t length = peerData.s().size(); size_t length = peerData.s().size();
if(length%6 == 0) { if(length%unit == 0) {
const char* base = peerData.s().data(); const unsigned char* base =
for(size_t i = 0; i < length; i += 6) { reinterpret_cast<const unsigned char*>(peerData.s().data());
struct in_addr in; const unsigned char* end = base+length;
memcpy(&in.s_addr, base+i, sizeof(uint32_t)); for(; base != end; base += unit) {
std::string ipaddr = inet_ntoa(in); std::pair<std::string, uint16_t> p = unpackcompact(base, family_);
uint16_t port_nworder; *dest_++ = SharedHandle<Peer>(new Peer(p.first, p.second));
memcpy(&port_nworder, base+i+4, sizeof(uint16_t));
uint16_t port = ntohs(port_nworder);
*dest_ = SharedHandle<Peer>(new Peer(ipaddr, port));
++dest_;
} }
} }
} }
@ -269,15 +276,16 @@ void extractPeer(const ValueBase* peerData, OutputIterator dest)
virtual void visit(const Dict& v) {} virtual void visit(const Dict& v) {}
}; };
if(peerData) { if(peerData) {
PeerListValueBaseVisitor visitor(dest); PeerListValueBaseVisitor visitor(dest, family);
peerData->accept(visitor); peerData->accept(visitor);
} }
} }
template<typename OutputIterator> template<typename OutputIterator>
void extractPeer(const SharedHandle<ValueBase>& peerData, OutputIterator dest) void extractPeer
(const SharedHandle<ValueBase>& peerData, int family, OutputIterator dest)
{ {
return extractPeer(peerData.get(), dest); return extractPeer(peerData.get(), family, dest);
} }
} // namespace bittorrent } // namespace bittorrent

View File

@ -56,15 +56,17 @@ class BittorrentHelperTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testSetFileFilter_multi); CPPUNIT_TEST(testSetFileFilter_multi);
CPPUNIT_TEST(testUTF8Torrent); CPPUNIT_TEST(testUTF8Torrent);
CPPUNIT_TEST(testEtc); CPPUNIT_TEST(testEtc);
CPPUNIT_TEST(testCreatecompact);
CPPUNIT_TEST(testCheckBitfield); CPPUNIT_TEST(testCheckBitfield);
CPPUNIT_TEST(testMetadata); CPPUNIT_TEST(testMetadata);
CPPUNIT_TEST(testParseMagnet); CPPUNIT_TEST(testParseMagnet);
CPPUNIT_TEST(testParseMagnet_base32); CPPUNIT_TEST(testParseMagnet_base32);
CPPUNIT_TEST(testMetadata2Torrent); CPPUNIT_TEST(testMetadata2Torrent);
CPPUNIT_TEST(testTorrent2Magnet); CPPUNIT_TEST(testTorrent2Magnet);
CPPUNIT_TEST(testExtractPeerFromString);
CPPUNIT_TEST(testExtractPeerFromList); CPPUNIT_TEST(testExtractPeerFromList);
CPPUNIT_TEST(testExtract2PeersFromList); CPPUNIT_TEST(testExtract2PeersFromList);
CPPUNIT_TEST(testPackcompact);
CPPUNIT_TEST(testUnpackcompact);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
public: public:
void setUp() { void setUp() {
@ -101,15 +103,17 @@ public:
void testSetFileFilter_multi(); void testSetFileFilter_multi();
void testUTF8Torrent(); void testUTF8Torrent();
void testEtc(); void testEtc();
void testCreatecompact();
void testCheckBitfield(); void testCheckBitfield();
void testMetadata(); void testMetadata();
void testParseMagnet(); void testParseMagnet();
void testParseMagnet_base32(); void testParseMagnet_base32();
void testMetadata2Torrent(); void testMetadata2Torrent();
void testTorrent2Magnet(); void testTorrent2Magnet();
void testExtractPeerFromString();
void testExtractPeerFromList(); void testExtractPeerFromList();
void testExtract2PeersFromList(); void testExtract2PeersFromList();
void testPackcompact();
void testUnpackcompact();
}; };
@ -645,18 +649,6 @@ void BittorrentHelperTest::testEtc()
getTorrentAttrs(dctx)->creationDate); getTorrentAttrs(dctx)->creationDate);
} }
void BittorrentHelperTest::testCreatecompact()
{
unsigned char compact[6];
// Note: bittorrent::createcompact() on linux can handle IPv4-mapped
// addresses like `ffff::127.0.0.1', but on cygwin, it doesn't.
CPPUNIT_ASSERT(createcompact(compact, "127.0.0.1", 6881));
std::pair<std::string, uint16_t> p = unpackcompact(compact);
CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), p.first);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
}
void BittorrentHelperTest::testCheckBitfield() void BittorrentHelperTest::testCheckBitfield()
{ {
unsigned char bitfield[] = { 0xff, 0xe0 }; unsigned char bitfield[] = { 0xff, 0xe0 };
@ -760,6 +752,35 @@ void BittorrentHelperTest::testTorrent2Magnet()
torrent2Magnet(getTorrentAttrs(dctx))); torrent2Magnet(getTorrentAttrs(dctx)));
} }
void BittorrentHelperTest::testExtractPeerFromString()
{
std::string hextext = "100210354527354678541237324732171ae1";
hextext += "20010db8bd0501d2288a1fc0000110ee1ae2";
std::string peersstr = "36:"+util::fromHex(hextext);
SharedHandle<ValueBase> str = bencode2::decode(peersstr);
std::deque<SharedHandle<Peer> > peers;
extractPeer(str, AF_INET6, std::back_inserter(peers));
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
CPPUNIT_ASSERT_EQUAL(std::string("1002:1035:4527:3546:7854:1237:3247:3217"),
peers[0]->getIPAddress());
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peers[0]->getPort());
CPPUNIT_ASSERT_EQUAL(std::string("2001:db8:bd05:1d2:288a:1fc0:1:10ee"),
peers[1]->getIPAddress());
CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
hextext = "c0a800011ae1";
hextext += "c0a800021ae2";
peersstr = "12:"+util::fromHex(hextext);
str = bencode2::decode(peersstr);
peers.clear();
extractPeer(str, AF_INET, std::back_inserter(peers));
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peers[0]->getIPAddress());
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peers[0]->getPort());
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.2"), peers[1]->getIPAddress());
CPPUNIT_ASSERT_EQUAL((uint16_t)6882, peers[1]->getPort());
}
void BittorrentHelperTest::testExtractPeerFromList() void BittorrentHelperTest::testExtractPeerFromList()
{ {
std::string peersString = std::string peersString =
@ -769,7 +790,7 @@ void BittorrentHelperTest::testExtractPeerFromList()
SharedHandle<ValueBase> dict = bencode2::decode(peersString); SharedHandle<ValueBase> dict = bencode2::decode(peersString);
std::deque<SharedHandle<Peer> > peers; std::deque<SharedHandle<Peer> > peers;
extractPeer(asDict(dict)->get("peers"), std::back_inserter(peers)); extractPeer(asDict(dict)->get("peers"), AF_INET, std::back_inserter(peers));
CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size()); CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
SharedHandle<Peer> peer = *peers.begin(); SharedHandle<Peer> peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress()); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress());
@ -786,7 +807,7 @@ void BittorrentHelperTest::testExtract2PeersFromList()
SharedHandle<ValueBase> dict = bencode2::decode(peersString); SharedHandle<ValueBase> dict = bencode2::decode(peersString);
std::deque<SharedHandle<Peer> > peers; std::deque<SharedHandle<Peer> > peers;
extractPeer(asDict(dict)->get("peers"), std::back_inserter(peers)); extractPeer(asDict(dict)->get("peers"), AF_INET, std::back_inserter(peers));
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
SharedHandle<Peer> peer = *peers.begin(); SharedHandle<Peer> peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress()); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer->getIPAddress());
@ -797,6 +818,40 @@ void BittorrentHelperTest::testExtract2PeersFromList()
CPPUNIT_ASSERT_EQUAL((uint16_t)2007, peer->getPort()); CPPUNIT_ASSERT_EQUAL((uint16_t)2007, peer->getPort());
} }
void BittorrentHelperTest::testPackcompact()
{
unsigned char compact[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT_EQUAL(18,
packcompact(compact,
"1002:1035:4527:3546:7854:1237:3247:3217",
6881));
CPPUNIT_ASSERT_EQUAL(std::string("100210354527354678541237324732171ae1"),
util::toHex(compact, 18));
CPPUNIT_ASSERT_EQUAL(6, packcompact(compact, "192.168.0.1", 6881));
CPPUNIT_ASSERT_EQUAL(std::string("c0a800011ae1"), util::toHex(compact, 6));
CPPUNIT_ASSERT_EQUAL(0, packcompact(compact, "badaddr", 6881));
}
void BittorrentHelperTest::testUnpackcompact()
{
unsigned char compact6[] = {
0x10, 0x02, 0x10, 0x35, 0x45, 0x27, 0x35, 0x46,
0x78, 0x54, 0x12, 0x37, 0x32, 0x47, 0x32, 0x17,
0x1A, 0xE1 };
std::pair<std::string, uint16_t> p =
unpackcompact(compact6, AF_INET6);
CPPUNIT_ASSERT_EQUAL(std::string("1002:1035:4527:3546:7854:1237:3247:3217"),
p.first);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
unsigned char compact[] = { 0xC0, 0xa8, 0x00, 0x01, 0x1A, 0xE1 };
p = unpackcompact(compact, AF_INET);
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), p.first);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
}
} // namespace bittorrent } // namespace bittorrent
} // namespace aria2 } // namespace aria2

View File

@ -45,12 +45,12 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1)); nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1));
nodes[i]->setPort(6881+i); nodes[i]->setPort(6881+i);
unsigned char buf[6]; unsigned char buf[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort())); (buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
compactNodeInfo += compactNodeInfo +=
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+ std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
std::string(&buf[0], &buf[sizeof(buf)]); std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
} }
msg.setClosestKNodes msg.setClosestKNodes
(std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K])); (std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K]));

View File

@ -57,12 +57,12 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1)); nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1));
nodes[i]->setPort(6881+i); nodes[i]->setPort(6881+i);
unsigned char buf[6]; unsigned char buf[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort())); (buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
compactNodeInfo += compactNodeInfo +=
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+ std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
std::string(&buf[0], &buf[sizeof(buf)]); std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
} }
msg.setClosestKNodes msg.setClosestKNodes
(std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K])); (std::vector<SharedHandle<DHTNode> >(&nodes[0], &nodes[DHTBucket::K]));
@ -80,10 +80,9 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
SharedHandle<List> valuesList = List::g(); SharedHandle<List> valuesList = List::g();
for(size_t i = 0; i < 4; ++i) { 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("192.168.0."+util::uitos(i+1), 6881+i));
unsigned char buffer[6]; unsigned char buffer[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact(buffer, peer->getIPAddress(), peer->getPort());
(buffer, peer->getIPAddress(), peer->getPort())); valuesList->append(String::g(buffer, COMPACT_LEN_IPV4));
valuesList->append(String::g(buffer, sizeof(buffer)));
peers.push_back(peer); peers.push_back(peer);
} }
rDict->put("values", valuesList); rDict->put("values", valuesList);

View File

@ -168,12 +168,12 @@ void DHTMessageFactoryImplTest::testCreateFindNodeReplyMessage()
nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1)); nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1));
nodes[i]->setPort(6881+i); nodes[i]->setPort(6881+i);
unsigned char buf[6]; unsigned char buf[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort())); (buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
compactNodeInfo += compactNodeInfo +=
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+ std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
std::string(&buf[0], &buf[sizeof(buf)]); std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
} }
rDict->put("nodes", compactNodeInfo); rDict->put("nodes", compactNodeInfo);
dict.put("r", rDict); dict.put("r", rDict);
@ -243,12 +243,12 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_nodes()
nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1)); nodes[i]->setIPAddress("192.168.0."+util::uitos(i+1));
nodes[i]->setPort(6881+i); nodes[i]->setPort(6881+i);
unsigned char buf[6]; unsigned char buf[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact
(buf, nodes[i]->getIPAddress(), nodes[i]->getPort())); (buf, nodes[i]->getIPAddress(), nodes[i]->getPort());
compactNodeInfo += compactNodeInfo +=
std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+ std::string(&nodes[i]->getID()[0], &nodes[i]->getID()[DHT_ID_LENGTH])+
std::string(&buf[0], &buf[sizeof(buf)]); std::string(&buf[0], &buf[COMPACT_LEN_IPV4]);
} }
rDict->put("nodes", compactNodeInfo); rDict->put("nodes", compactNodeInfo);
rDict->put("token", "token"); rDict->put("token", "token");
@ -290,10 +290,10 @@ void DHTMessageFactoryImplTest::testCreateGetPeersReplyMessage_values()
SharedHandle<List> valuesList = List::g(); SharedHandle<List> valuesList = List::g();
for(size_t i = 0; i < 4; ++i) { 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("192.168.0."+util::uitos(i+1), 6881+i));
unsigned char buffer[6]; unsigned char buffer[COMPACT_LEN_IPV6];
CPPUNIT_ASSERT(bittorrent::createcompact bittorrent::packcompact
(buffer, peer->getIPAddress(), peer->getPort())); (buffer, peer->getIPAddress(), peer->getPort());
valuesList->append(String::g(buffer, sizeof(buffer))); valuesList->append(String::g(buffer, COMPACT_LEN_IPV4));
peers.push_back(peer); peers.push_back(peer);
} }
rDict->put("values", valuesList); rDict->put("values", valuesList);

View File

@ -115,7 +115,8 @@ void DHTRoutingTableSerializerTest::testSerialize()
ss.read(buf, 6); ss.read(buf, 6);
{ {
std::pair<std::string, uint16_t> peer = std::pair<std::string, uint16_t> peer =
bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf)); bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
AF_INET);
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer.first); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.1"), peer.first);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second); CPPUNIT_ASSERT_EQUAL((uint16_t)6881, peer.second);
} }
@ -174,7 +175,8 @@ void DHTRoutingTableSerializerTest::testSerialize()
ss.read(buf, 6); ss.read(buf, 6);
{ {
std::pair<std::string, uint16_t> peer = std::pair<std::string, uint16_t> peer =
bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf)); bittorrent::unpackcompact(reinterpret_cast<const unsigned char*>(buf),
AF_INET);
CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.3"), peer.first); CPPUNIT_ASSERT_EQUAL(std::string("192.168.0.3"), peer.first);
CPPUNIT_ASSERT_EQUAL((uint16_t)6883, peer.second); CPPUNIT_ASSERT_EQUAL((uint16_t)6883, peer.second);
} }

View File

@ -131,14 +131,14 @@ void DefaultExtensionMessageFactoryTest::testCreateMessage_Handshake()
void DefaultExtensionMessageFactoryTest::testCreateMessage_UTPex() void DefaultExtensionMessageFactoryTest::testCreateMessage_UTPex()
{ {
unsigned char c1[6]; unsigned char c1[COMPACT_LEN_IPV6];
unsigned char c2[6]; unsigned char c2[COMPACT_LEN_IPV6];
unsigned char c3[6]; unsigned char c3[COMPACT_LEN_IPV6];
unsigned char c4[6]; unsigned char c4[COMPACT_LEN_IPV6];
bittorrent::createcompact(c1, "192.168.0.1", 6881); bittorrent::packcompact(c1, "192.168.0.1", 6881);
bittorrent::createcompact(c2, "10.1.1.2", 9999); bittorrent::packcompact(c2, "10.1.1.2", 9999);
bittorrent::createcompact(c3, "192.168.0.2", 6882); bittorrent::packcompact(c3, "192.168.0.2", 6882);
bittorrent::createcompact(c4, "10.1.1.3",10000); bittorrent::packcompact(c4, "10.1.1.3",10000);
std::string data = getExtensionMessageID("ut_pex")+"d5:added12:"+ std::string data = getExtensionMessageID("ut_pex")+"d5:added12:"+
std::string(&c1[0], &c1[6])+std::string(&c2[0], &c2[6])+ std::string(&c1[0], &c1[6])+std::string(&c2[0], &c2[6])+

View File

@ -81,18 +81,18 @@ void UTPexExtensionMessageTest::testGetBencodedData()
p4->startBadCondition(); p4->startBadCondition();
CPPUNIT_ASSERT(msg.addDroppedPeer(p4)); CPPUNIT_ASSERT(msg.addDroppedPeer(p4));
unsigned char c1[6]; unsigned char c1[COMPACT_LEN_IPV6];
unsigned char c2[6]; unsigned char c2[COMPACT_LEN_IPV6];
unsigned char c3[6]; unsigned char c3[COMPACT_LEN_IPV6];
unsigned char c4[6]; unsigned char c4[COMPACT_LEN_IPV6];
bittorrent::createcompact(c1, p1->getIPAddress(), p1->getPort()); bittorrent::packcompact(c1, p1->getIPAddress(), p1->getPort());
bittorrent::createcompact(c2, p2->getIPAddress(), p2->getPort()); bittorrent::packcompact(c2, p2->getIPAddress(), p2->getPort());
bittorrent::createcompact(c3, p3->getIPAddress(), p3->getPort()); bittorrent::packcompact(c3, p3->getIPAddress(), p3->getPort());
bittorrent::createcompact(c4, p4->getIPAddress(), p4->getPort()); bittorrent::packcompact(c4, p4->getIPAddress(), p4->getPort());
std::string expected = "d5:added12:"+ std::string expected = "d5:added12:"+
std::string(&c1[0], &c1[6])+std::string(&c2[0], &c2[6])+ std::string(&c1[0], &c1[6])+std::string(&c2[0], &c2[6])+
"7:added.f2:207:dropped12:"+ "7:added.f2:"+util::fromHex("0200")+"7:dropped12:"+
std::string(&c3[0], &c3[6])+std::string(&c4[0], &c4[6])+ std::string(&c3[0], &c3[6])+std::string(&c4[0], &c4[6])+
"e"; "e";
std::string bd = msg.getPayload(); std::string bd = msg.getPayload();
@ -152,14 +152,14 @@ void UTPexExtensionMessageTest::testDoReceivedAction()
void UTPexExtensionMessageTest::testCreate() void UTPexExtensionMessageTest::testCreate()
{ {
unsigned char c1[6]; unsigned char c1[COMPACT_LEN_IPV6];
unsigned char c2[6]; unsigned char c2[COMPACT_LEN_IPV6];
unsigned char c3[6]; unsigned char c3[COMPACT_LEN_IPV6];
unsigned char c4[6]; unsigned char c4[COMPACT_LEN_IPV6];
bittorrent::createcompact(c1, "192.168.0.1", 6881); bittorrent::packcompact(c1, "192.168.0.1", 6881);
bittorrent::createcompact(c2, "10.1.1.2", 9999); bittorrent::packcompact(c2, "10.1.1.2", 9999);
bittorrent::createcompact(c3, "192.168.0.2", 6882); bittorrent::packcompact(c3, "192.168.0.2", 6882);
bittorrent::createcompact(c4, "10.1.1.3",10000); bittorrent::packcompact(c4, "10.1.1.3",10000);
char id[1] = { 1 }; char id[1] = { 1 };