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

Added v key in DHT message. aria2's DHT version is independent of
	the package version and we defined it as 1 at the moment. It is
	defined as DHT_VERSION in src/DHTConstants.h. aria2's DHT version
	scheme is "A2"+2bytes DHT version number in network byte order.
	* src/DHTAbstractMessage.cc
	* src/DHTConstants.h
	* src/DHTMessage.cc
	* src/DHTMessage.h
	* src/DHTMessageFactoryImpl.cc
	* src/DHTQueryMessage.cc
	* src/DHTResponseMessage.cc
	* src/util.h
	* test/DHTAnnouncePeerMessageTest.cc
	* test/DHTAnnouncePeerReplyMessageTest.cc
	* test/DHTFindNodeMessageTest.cc
	* test/DHTFindNodeReplyMessageTest.cc
	* test/DHTGetPeersMessageTest.cc
	* test/DHTGetPeersReplyMessageTest.cc
	* test/DHTPingMessageTest.cc
	* test/DHTPingReplyMessageTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-03-20 09:10:23 +00:00
parent d6860e11bf
commit 10edc156ea
17 changed files with 129 additions and 33 deletions

View File

@ -1,3 +1,26 @@
2010-03-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added v key in DHT message. aria2's DHT version is independent of
the package version and we defined it as 1 at the moment. It is
defined as DHT_VERSION in src/DHTConstants.h. aria2's DHT version
scheme is "A2"+2bytes DHT version number in network byte order.
* src/DHTAbstractMessage.cc
* src/DHTConstants.h
* src/DHTMessage.cc
* src/DHTMessage.h
* src/DHTMessageFactoryImpl.cc
* src/DHTQueryMessage.cc
* src/DHTResponseMessage.cc
* src/util.h
* test/DHTAnnouncePeerMessageTest.cc
* test/DHTAnnouncePeerReplyMessageTest.cc
* test/DHTFindNodeMessageTest.cc
* test/DHTFindNodeReplyMessageTest.cc
* test/DHTGetPeersMessageTest.cc
* test/DHTGetPeersReplyMessageTest.cc
* test/DHTPingMessageTest.cc
* test/DHTPingReplyMessageTest.cc
2010-03-19 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that value of numSeeders in aria2.tellStatus XML-RPC

View File

@ -58,6 +58,7 @@ std::string DHTAbstractMessage::getBencodedMessage()
BDE msgDict = BDE::dict();
msgDict[T] = _transactionID;
msgDict[Y] = getType();
msgDict[V] = _version;
fillMessage(msgDict);
return bencode::encode(msgDict);
}

View File

@ -35,6 +35,10 @@
#ifndef _D_DHT_CONSTANTS_H_
#define _D_DHT_CONSTANTS_H_
// Increment this if major improvements or bug fixes are made in DHT
// code.
#define DHT_VERSION 1
#define DHT_ID_LENGTH 20
#define DHT_TRANSACTION_ID_LENGTH 2

View File

@ -42,6 +42,8 @@ const std::string DHTMessage::Y("y");
const std::string DHTMessage::T("t");
const std::string DHTMessage::V("v");
const std::string DHTMessage::ID("id");
DHTMessage::DHTMessage(const SharedHandle<DHTNode>& localNode,

View File

@ -54,6 +54,8 @@ protected:
std::string _transactionID;
std::string _version;
void generateTransactionID();
public:
DHTMessage(const SharedHandle<DHTNode>& localNode,
@ -89,10 +91,17 @@ public:
virtual std::string toString() const = 0;
void setVersion(const std::string& version)
{
_version = version;
}
static const std::string Y;
static const std::string T;
static const std::string V;
static const std::string ID;
};

View File

@ -174,6 +174,16 @@ void DHTMessageFactoryImpl::validatePort(const BDE& i) const
}
}
static void setVersion(const SharedHandle<DHTMessage>& msg, const BDE& dict)
{
const BDE& v = dict[DHTMessage::V];
if(v.isString()) {
msg->setVersion(v.s());
} else {
msg->setVersion(A2STR::NIL);
}
}
SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
(const BDE& dict,
const std::string& ipaddr,
@ -189,20 +199,21 @@ SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
const BDE& id = getString(aDict, DHTMessage::ID);
validateID(id);
SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port);
SharedHandle<DHTMessage> msg;
if(messageType.s() == DHTPingMessage::PING) {
return createPingMessage(remoteNode, transactionID.s());
msg = createPingMessage(remoteNode, transactionID.s());
} else if(messageType.s() == DHTFindNodeMessage::FIND_NODE) {
const BDE& targetNodeID =
getString(aDict, DHTFindNodeMessage::TARGET_NODE);
validateID(targetNodeID);
return createFindNodeMessage(remoteNode, targetNodeID.uc(),
transactionID.s());
msg = createFindNodeMessage(remoteNode, targetNodeID.uc(),
transactionID.s());
} else if(messageType.s() == DHTGetPeersMessage::GET_PEERS) {
const BDE& infoHash =
getString(aDict, DHTGetPeersMessage::INFO_HASH);
validateID(infoHash);
return createGetPeersMessage(remoteNode,
infoHash.uc(), transactionID.s());
msg = createGetPeersMessage(remoteNode,
infoHash.uc(), transactionID.s());
} else if(messageType.s() == DHTAnnouncePeerMessage::ANNOUNCE_PEER) {
const BDE& infoHash =
getString(aDict, DHTAnnouncePeerMessage::INFO_HASH);
@ -210,14 +221,16 @@ SharedHandle<DHTMessage> DHTMessageFactoryImpl::createQueryMessage
const BDE& port = getInteger(aDict, DHTAnnouncePeerMessage::PORT);
validatePort(port);
const BDE& token = getString(aDict, DHTAnnouncePeerMessage::TOKEN);
return createAnnouncePeerMessage(remoteNode, infoHash.uc(),
static_cast<uint16_t>(port.i()),
token.s(), transactionID.s());
msg = createAnnouncePeerMessage(remoteNode, infoHash.uc(),
static_cast<uint16_t>(port.i()),
token.s(), transactionID.s());
} else {
throw DL_ABORT_EX
(StringFormat("Unsupported message type: %s",
messageType.s().c_str()).str());
}
setVersion(msg, dict);
return msg;
}
SharedHandle<DHTMessage>
@ -252,31 +265,46 @@ DHTMessageFactoryImpl::createResponseMessage(const std::string& messageType,
const BDE& id = getString(rDict, DHTMessage::ID);
validateID(id);
SharedHandle<DHTNode> remoteNode = getRemoteNode(id.uc(), ipaddr, port);
SharedHandle<DHTMessage> msg;
if(messageType == DHTPingReplyMessage::PING) {
return createPingReplyMessage(remoteNode, id.uc(), transactionID.s());
msg = createPingReplyMessage(remoteNode, id.uc(), transactionID.s());
} else if(messageType == DHTFindNodeReplyMessage::FIND_NODE) {
return createFindNodeReplyMessage(remoteNode, dict, transactionID.s());
msg = createFindNodeReplyMessage(remoteNode, dict, transactionID.s());
} else if(messageType == DHTGetPeersReplyMessage::GET_PEERS) {
const BDE& valuesList = rDict[DHTGetPeersReplyMessage::VALUES];
if(valuesList.isList()) {
return createGetPeersReplyMessageWithValues(remoteNode, dict,
transactionID.s());
msg = createGetPeersReplyMessageWithValues(remoteNode, dict,
transactionID.s());
} else {
const BDE& nodes = rDict[DHTGetPeersReplyMessage::NODES];
if(nodes.isString()) {
return createGetPeersReplyMessageWithNodes(remoteNode, dict,
msg = createGetPeersReplyMessageWithNodes(remoteNode, dict,
transactionID.s());
} else {
throw DL_ABORT_EX("Malformed DHT message: missing nodes/values");
}
}
} else if(messageType == DHTAnnouncePeerReplyMessage::ANNOUNCE_PEER) {
return createAnnouncePeerReplyMessage(remoteNode, transactionID.s());
msg = createAnnouncePeerReplyMessage(remoteNode, transactionID.s());
} else {
throw DL_ABORT_EX
(StringFormat("Unsupported message type: %s", messageType.c_str()).str());
}
setVersion(msg, dict);
return msg;
}
static const std::string& getDefaultVersion()
{
static std::string version;
if(version.empty()) {
uint16_t vnum16 = htons(DHT_VERSION);
unsigned char buf[] = { 'A' , '2', 0, 0 };
char* vnump = reinterpret_cast<char*>(&vnum16);
memcpy(buf+2, vnump, 2);
version.assign(&buf[0], &buf[4]);
}
return version;
}
void DHTMessageFactoryImpl::setCommonProperty(const SharedHandle<DHTAbstractMessage>& m)
@ -286,6 +314,7 @@ void DHTMessageFactoryImpl::setCommonProperty(const SharedHandle<DHTAbstractMess
m->setRoutingTable(_routingTable);
WeakHandle<DHTMessageFactory> factory(this);
m->setMessageFactory(factory);
m->setVersion(getDefaultVersion());
}
SharedHandle<DHTMessage> DHTMessageFactoryImpl::createPingMessage(const SharedHandle<DHTNode>& remoteNode, const std::string& transactionID)

View File

@ -69,12 +69,20 @@ bool DHTQueryMessage::isReply() const
std::string DHTQueryMessage::toString() const
{
return strconcat("dht query ", getMessageType(),
" TransactionID=", util::toHex(_transactionID),
" Remote:", _remoteNode->getIPAddress(),
":", util::uitos(_remoteNode->getPort()),
", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
", ", toStringOptional());
std::string s = strconcat
("dht query ", getMessageType(),
" TransactionID=", util::toHex(_transactionID),
" Remote:", _remoteNode->getIPAddress(),
":", util::uitos(_remoteNode->getPort()),
", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
", ");
if(!_version.empty()) {
s += "v=";
s += util::torrentPercentEncode(_version);
s += ", ";
}
s += toStringOptional();
return s;
}
} // namespace aria2

View File

@ -66,12 +66,20 @@ bool DHTResponseMessage::isReply() const
std::string DHTResponseMessage::toString() const
{
return strconcat("dht response ", getMessageType(),
" TransactionID=", util::toHex(_transactionID),
" Remote:", _remoteNode->getIPAddress(),
":", util::uitos(_remoteNode->getPort()),
", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
", ", toStringOptional());
std::string s = strconcat
("dht response ", getMessageType(),
" TransactionID=", util::toHex(_transactionID),
" Remote:", _remoteNode->getIPAddress(),
":", util::uitos(_remoteNode->getPort()),
", id=", util::toHex(_remoteNode->getID(), DHT_ID_LENGTH),
", ");
if(!_version.empty()) {
s += "v=";
s += util::torrentPercentEncode(_version);
s += ", ";
}
s += toStringOptional();
return s;
}
} // namespace aria2

View File

@ -242,6 +242,8 @@ void usleep(long microseconds);
bool isNumber(const std::string& what);
bool isDigit(const char c);
bool isHexDigit(const char c);
bool isHexDigit(const std::string& s);

View File

@ -56,11 +56,12 @@ void DHTAnnouncePeerMessageTest::testGetBencodedMessage()
uint16_t port = 6881;
DHTAnnouncePeerMessage msg(localNode, remoteNode, infoHash, port, token, transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("q");
dict["q"] = BDE("announce_peer");
BDE aDict = BDE::dict();

View File

@ -35,11 +35,12 @@ void DHTAnnouncePeerReplyMessageTest::testGetBencodedMessage()
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
DHTAnnouncePeerReplyMessage msg(localNode, remoteNode, transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("r");
BDE rDict = BDE::dict();
rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

View File

@ -58,11 +58,12 @@ void DHTFindNodeMessageTest::testGetBencodedMessage()
SharedHandle<DHTNode> targetNode(new DHTNode());
DHTFindNodeMessage msg(localNode, remoteNode, targetNode->getID(), transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("q");
dict["q"] = BDE("find_node");
BDE aDict = BDE::dict();

View File

@ -37,7 +37,7 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
DHTFindNodeReplyMessage msg(localNode, remoteNode, transactionID);
msg.setVersion("A200");
std::string compactNodeInfo;
SharedHandle<DHTNode> nodes[8];
for(size_t i = 0; i < DHTBucket::K; ++i) {
@ -59,6 +59,7 @@ void DHTFindNodeReplyMessageTest::testGetBencodedMessage()
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("r");
BDE rDict = BDE::dict();
rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

View File

@ -77,11 +77,13 @@ void DHTGetPeersMessageTest::testGetBencodedMessage()
util::generateRandomData(infoHash, DHT_ID_LENGTH);
DHTGetPeersMessage msg(localNode, remoteNode, infoHash, transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("q");
dict["q"] = BDE("get_peers");
BDE aDict = BDE::dict();

View File

@ -40,9 +40,10 @@ void DHTGetPeersReplyMessageTest::testGetBencodedMessage()
std::string token = "token";
DHTGetPeersReplyMessage msg(localNode, remoteNode, token, transactionID);
msg.setVersion("A200");
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("r");
BDE rDict = BDE::dict();
rDict["id"] = BDE(localNode->getID(), DHT_ID_LENGTH);

View File

@ -53,11 +53,13 @@ void DHTPingMessageTest::testGetBencodedMessage()
std::string transactionID(&tid[0], &tid[DHT_TRANSACTION_ID_LENGTH]);
DHTPingMessage msg(localNode, remoteNode, transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("q");
dict["q"] = BDE("ping");
BDE aDict = BDE::dict();

View File

@ -38,11 +38,12 @@ void DHTPingReplyMessageTest::testGetBencodedMessage()
util::generateRandomData(id, DHT_ID_LENGTH);
DHTPingReplyMessage msg(localNode, remoteNode, id, transactionID);
msg.setVersion("A200");
std::string msgbody = msg.getBencodedMessage();
BDE dict = BDE::dict();
dict["t"] = transactionID;
dict["v"] = BDE("A200");
dict["y"] = BDE("r");
BDE rDict = BDE::dict();
rDict["id"] = BDE(id, DHT_ID_LENGTH);