2007-12-22 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Added uTorrent compatible Peer Exchange.
	* src/BencodeVisitor.{h, cc}
	* test/BencodeVisitorTest.cc
	* src/BtConstants.h
	* src/BtContext.h: Added 'private' flag.
	* src/BtExtendedMessage.{h, cc}
	* test/BtExtendedMessageTest.cc
	* src/BtHandshakeMessage.{h, cc}: Set extended messaging bit in
	reserved field.
	* test/BtHandshakeMessageTest.cc
	* src/BtMessageFactory.h
	* src/BtRegistry.h
	* src/BtRuntime.h: This class holds default extension message 
IDs for
	aria2. By default, aria2 uses ID 8 for ut_pex.
	* src/DefaultBtContext.cc
	* src/DefaultBtInteractive.{h, cc}: This class holds 
_utPexEnabled.
	When it is true, aria2 enables ut_pex. This value is set by
	PeerInteractionCommand.
	* src/DefaultBtMessageFactory.{h, cc}
	* test/DefaultBtMessageFactoryTest.cc
	* src/DefaultBtMessageReceiver.cc: Moved the code of fast 
extension
	handling to DefaultBtInteractive class.
	* src/DefaultExtensionMessageFactory.{h, cc}
	* test/DefaultExtensionMessageFactoryTest.cc
	* src/DefaultPeerStorage.cc: Returns false if a peer is already 
in
	the container(peers and incomingPeers. The equality is 
determined by
	Peer::id).
	* test/DefaultPeerStorageTest.cc
	* src/ExtensionMessage.h
	* test/MockExtensionMessage.h
	* src/ExtensionMessageFactory.h
	* test/MockExtensionMessageFactory.h
	* src/HandshakeExtensionMessage.{h, cc}
	* test/HandshakeExtensionMessageTest.cc
	* src/MetaEntry.h
	* src/Peer.{h, cc}
	* src/PeerInteractionCommand.cc
	* src/PeerReceiveHandshakeCommand.cc: Evaluate the return value 
of
	addIncomingPeer.
	* src/PeerMessageUtil.{h, cc}
	* src/PeerObject.h
	* src/UTPexExtensionMessage.{h, cc}
	* test/UTPexExtensionMessageTest.cc
	* src/message.h
	* src/prefs.h

	Fixed the bug that returns incomplete data when it contains null
	character. A convenient constructor was also added.
	* src/Data.{h, cc}

	Rewritten.
	* src/CompactPeerListProcessor.cc

	Fixed typos.
	* src/message.h
	* src/MetaFileUtil.cc
pull/1/head
Tatsuhiro Tsujikawa 2007-12-22 03:57:55 +00:00
parent c25f4cffc0
commit 286f34cb3f
61 changed files with 2487 additions and 100 deletions

View File

@ -1,3 +1,62 @@
2007-12-22 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Added uTorrent compatible Peer Exchange.
* src/BencodeVisitor.{h, cc}
* test/BencodeVisitorTest.cc
* src/BtConstants.h
* src/BtContext.h: Added 'private' flag.
* src/BtExtendedMessage.{h, cc}
* test/BtExtendedMessageTest.cc
* src/BtHandshakeMessage.{h, cc}: Set extended messaging bit in
reserved field.
* test/BtHandshakeMessageTest.cc
* src/BtMessageFactory.h
* src/BtRegistry.h
* src/BtRuntime.h: This class holds default extension message IDs for
aria2. By default, aria2 uses ID 8 for ut_pex.
* src/DefaultBtContext.cc
* src/DefaultBtInteractive.{h, cc}: This class holds _utPexEnabled.
When it is true, aria2 enables ut_pex. This value is set by
PeerInteractionCommand.
* src/DefaultBtMessageFactory.{h, cc}
* test/DefaultBtMessageFactoryTest.cc
* src/DefaultBtMessageReceiver.cc: Moved the code of fast extension
handling to DefaultBtInteractive class.
* src/DefaultExtensionMessageFactory.{h, cc}
* test/DefaultExtensionMessageFactoryTest.cc
* src/DefaultPeerStorage.cc: Returns false if a peer is already in
the container(peers and incomingPeers. The equality is determined by
Peer::id).
* test/DefaultPeerStorageTest.cc
* src/ExtensionMessage.h
* test/MockExtensionMessage.h
* src/ExtensionMessageFactory.h
* test/MockExtensionMessageFactory.h
* src/HandshakeExtensionMessage.{h, cc}
* test/HandshakeExtensionMessageTest.cc
* src/MetaEntry.h
* src/Peer.{h, cc}
* src/PeerInteractionCommand.cc
* src/PeerReceiveHandshakeCommand.cc: Evaluate the return value of
addIncomingPeer.
* src/PeerMessageUtil.{h, cc}
* src/PeerObject.h
* src/UTPexExtensionMessage.{h, cc}
* test/UTPexExtensionMessageTest.cc
* src/message.h
* src/prefs.h
Fixed the bug that returns incomplete data when it contains null
character. A convenient constructor was also added.
* src/Data.{h, cc}
Rewritten.
* src/CompactPeerListProcessor.cc
Fixed typos.
* src/message.h
* src/MetaFileUtil.cc
2007-12-16 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Added "Status Legend" label to the explanation text of 'stat' in

84
src/BencodeVisitor.cc Normal file
View File

@ -0,0 +1,84 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "BencodeVisitor.h"
#include "Data.h"
#include "List.h"
#include "Dictionary.h"
#include "Util.h"
BencodeVisitor::BencodeVisitor() {}
BencodeVisitor::~BencodeVisitor() {}
void BencodeVisitor::visit(const Data* d)
{
if(d->isNumber()) {
_bencodedData += "i"+d->toString()+"e";
} else {
_bencodedData += Util::itos(d->getLen())+":"+d->toString();
}
}
void BencodeVisitor::visit(const List* l)
{
_bencodedData += "l";
for_each(l->getList().begin(), l->getList().end(),
bind2nd(mem_fun(&MetaEntry::accept), this));
_bencodedData += "e";
}
void BencodeVisitor::visit(const Dictionary* d)
{
_bencodedData += "d";
for(Order::const_iterator itr = d->getOrder().begin(); itr != d->getOrder().end(); ++itr) {
_bencodedData += Util::itos((int32_t)(*itr).size());
_bencodedData += ":";
_bencodedData += *itr;
d->get(*itr)->accept(this);
}
_bencodedData += "e";
}
void BencodeVisitor::visit(const MetaEntry* e)
{
if(dynamic_cast<const Data*>(e) != 0) {
visit((const Data*)e);
} else if(dynamic_cast<const List*>(e) != 0) {
visit((const List*)e);
} else if(dynamic_cast<const Dictionary*>(e) != 0) {
visit((const Dictionary*)e);
}
}

64
src/BencodeVisitor.h Normal file
View File

@ -0,0 +1,64 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BENCODE_VISITOR_H_
#define _D_BENCODE_VISITOR_H_
#include "MetaEntryVisitor.h"
class Data;
class Dictionary;
class List;
class MetaEntry;
class BencodeVisitor : public MetaEntryVisitor {
private:
string _bencodedData;
public:
BencodeVisitor();
~BencodeVisitor();
void visit(const Data* d);
void visit(const Dictionary* d);
void visit(const List* l);
virtual void visit(const MetaEntry* e);
const string& getBencodedData() const
{
return _bencodedData;
}
};
#endif // _D_BENCODE_VISITOR_H_

43
src/BtConstants.h Normal file
View File

@ -0,0 +1,43 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BT_CONSTANTS_
#define _D_BT_CONSTANTS_
#include "common.h"
#include <map>
typedef map<string, uint8_t> Extensions;
#endif // _D_BT_CONSTANTS_

View File

@ -48,7 +48,11 @@ typedef deque<AnnounceTierHandle> AnnounceTiers;
class RequestGroup;
class BtContext:public DownloadContext {
protected:
bool _private;
public:
BtContext():_private(false) {}
virtual ~BtContext() {}
virtual const unsigned char* getInfoHash() const = 0;
@ -66,6 +70,11 @@ public:
*/
virtual const unsigned char* getPeerId() = 0;
bool isPrivate() const
{
return _private;
}
virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
virtual RequestGroup* getOwnerRequestGroup() = 0;

115
src/BtExtendedMessage.cc Normal file
View File

@ -0,0 +1,115 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "BtExtendedMessage.h"
#include "BtRegistry.h"
#include "ExtensionMessage.h"
#include "PeerMessageUtil.h"
#include "DlAbortEx.h"
#include "message.h"
#include "Util.h"
BtExtendedMessage::BtExtendedMessage(const ExtensionMessageHandle& extensionMessage):_extensionMessage(extensionMessage), _msg(0), _msgLength(0)
{}
BtExtendedMessage::~BtExtendedMessage()
{
delete [] _msg;
}
const unsigned char* BtExtendedMessage::getMessage() {
if(!_msg) {
/**
* len --- 2+extpayload.length, 4bytes
* id --- 20, 1byte
* extmsgid --- extmsgid, 1byte
* extpayload --- extpayload, nbytes
* total: 6+extpayload.length bytes
*/
string payload = _extensionMessage->getBencodedData();
_msgLength = 6+payload.size();
_msg = new unsigned char[_msgLength];
PeerMessageUtil::createPeerMessageString(_msg, _msgLength, 2+payload.size(), ID);
*(_msg+5) = _extensionMessage->getExtensionMessageID();
memcpy(_msg+6, payload.c_str(), payload.size());
}
return _msg;
}
int32_t BtExtendedMessage::getMessageLength() {
getMessage();
return _msgLength;
}
bool BtExtendedMessage::sendPredicate() const
{
return peer->isExtendedMessagingEnabled();
}
string BtExtendedMessage::toString() const {
return "extended "+_extensionMessage->toString();
}
BtExtendedMessageHandle
BtExtendedMessage::create(const BtContextHandle& btContext,
const PeerHandle& peer,
const char* data, size_t dataLength)
{
if(dataLength < 2) {
throw new DlAbortEx(MSG_TOO_SMALL_PAYLOAD_SIZE, "extended", dataLength);
}
int8_t id = PeerMessageUtil::getId((const unsigned char*)data);
if(id != ID) {
throw new DlAbortEx(EX_INVALID_BT_MESSAGE_ID, id, "extended", ID);
}
ExtensionMessageFactoryHandle factory = EXTENSION_MESSAGE_FACTORY(btContext,
peer);
assert(!factory.isNull());
ExtensionMessageHandle extmsg = factory->createMessage(data+1,
dataLength-1);
BtExtendedMessageHandle message = new BtExtendedMessage(extmsg);
return message;
}
void BtExtendedMessage::doReceivedAction()
{
if(!_extensionMessage.isNull()) {
_extensionMessage->doReceivedAction();
}
}
ExtensionMessageHandle BtExtendedMessage::getExtensionMessage() const
{
return _extensionMessage;
}

79
src/BtExtendedMessage.h Normal file
View File

@ -0,0 +1,79 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_BT_EXTENDED_MESSAGE_H_
#define _D_BT_EXTENDED_MESSAGE_H_
#include "SimpleBtMessage.h"
class BtExtendedMessage;
typedef SharedHandle<BtExtendedMessage> BtExtendedMessageHandle;
class ExtensionMessage;
typedef SharedHandle<ExtensionMessage> ExtensionMessageHandle;
class BtExtendedMessage:public SimpleBtMessage
{
private:
ExtensionMessageHandle _extensionMessage;
unsigned char* _msg;
size_t _msgLength;
public:
BtExtendedMessage(const ExtensionMessageHandle& extensionMessage = 0);
virtual ~BtExtendedMessage();
static const uint8_t ID = 20;
static BtExtendedMessageHandle create(const BtContextHandle& btContext,
const PeerHandle& peer,
const char* data,
size_t dataLength);
virtual int8_t getId() { return ID; }
virtual void doReceivedAction();
virtual const unsigned char* getMessage();
virtual int32_t getMessageLength();
virtual bool sendPredicate() const;
virtual string toString() const;
ExtensionMessageHandle getExtensionMessage() const;
};
#endif // _D_BT_EXTENDED_MESSAGE_H_

View File

@ -61,6 +61,8 @@ void BtHandshakeMessage::init() {
memset(this->reserved, 0, RESERVED_LENGTH);
// fast extension
this->reserved[7] |= 0x04;
// extended messaging
this->reserved[5] |= 0x10;
}
BtHandshakeMessageHandle BtHandshakeMessage::create(const unsigned char* data, int32_t dataLength) {
@ -98,3 +100,8 @@ string BtHandshakeMessage::toString() const {
bool BtHandshakeMessage::isFastExtensionSupported() const {
return reserved[7]&0x04;
}
bool BtHandshakeMessage::isExtendedMessagingEnabled() const
{
return reserved[5]&0x10;
}

View File

@ -87,6 +87,8 @@ public:
bool isFastExtensionSupported() const;
bool isExtendedMessagingEnabled() const;
int8_t getPstrlen() const {
return pstrlen;
}

View File

@ -39,6 +39,9 @@
#include "BtMessage.h"
#include "Piece.h"
class ExtensionMessage;
typedef SharedHandle<ExtensionMessage> ExensionMessageHandle;
class BtMessageFactory {
public:
virtual ~BtMessageFactory() {}
@ -84,6 +87,8 @@ public:
createRejectMessage(int32_t index, int32_t begin, int32_t length) = 0;
virtual BtMessageHandle createAllowedFastMessage(int32_t index) = 0;
virtual BtMessageHandle createBtExtendedMessage(const ExensionMessageHandle& msg) = 0;
};
typedef SharedHandle<BtMessageFactory> BtMessageFactoryHandle;

View File

@ -146,4 +146,7 @@ PEER_OBJECT(btContext, peer)->btRequestFactory
#define PEER_CONNECTION(btContext, peer) \
PEER_OBJECT(btContext, peer)->peerConnection
#define EXTENSION_MESSAGE_FACTORY(btContext, peer) \
PEER_OBJECT(btContext, peer)->extensionMessageFactory
#endif // _D_BT_REGISTRY_H_

View File

@ -36,7 +36,7 @@
#define _D_BT_RUNTIME_H_
#include "common.h"
#include "SharedHandle.h"
#include "BtConstants.h"
#define MIN_PEERS 40
@ -47,6 +47,8 @@ private:
bool halt;
int32_t connections;
bool _ready;
Extensions _extensions;
public:
BtRuntime():
uploadLengthAtStartup(0),
@ -54,7 +56,9 @@ public:
halt(false),
connections(0),
_ready(false)
{}
{
_extensions["ut_pex"] = 8;
}
~BtRuntime() {}
int64_t getUploadLengthAtStartup() const {
@ -90,6 +94,33 @@ public:
bool ready() { return _ready; }
void setReady(bool go) { _ready = go; }
const Extensions& getExtensions() const
{
return _extensions;
}
uint8_t getExtensionMessageID(const string& name)
{
Extensions::const_iterator itr = _extensions.find(name);
if(itr == _extensions.end()) {
return 0;
} else {
return (*itr).second;
}
}
string getExtensionName(uint8_t id)
{
for(Extensions::const_iterator itr = _extensions.begin();
itr != _extensions.end(); ++itr) {
const Extensions::value_type& p = *itr;
if(p.second == id) {
return p.first;
}
}
return "";
}
};
typedef SharedHandle<BtRuntime> BtRuntimeHandle;

View File

@ -43,19 +43,13 @@ Peers CompactPeerListProcessor::extractPeer(const MetaEntry* peersEntry) {
Peers peers;
const Data* peersData = (const Data*)peersEntry;
if(peersData->getLen() > 0) {
if(peersData->getLen()%6 == 0) {
for(int32_t i = 0; i < peersData->getLen(); i += 6) {
uint32_t ipaddr1 = (unsigned char)*(peersData->getData()+i);
uint32_t ipaddr2 = (unsigned char)*(peersData->getData()+i+1);
uint32_t ipaddr3 = (unsigned char)*(peersData->getData()+i+2);
uint32_t ipaddr4 = (unsigned char)*(peersData->getData()+i+3);
int32_t port = ntohs(*(uint16_t*)(peersData->getData()+i+4));
char ipaddr[16];
snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d",
ipaddr1, ipaddr2, ipaddr3, ipaddr4);
struct in_addr in;
in.s_addr = *(uint32_t*)(peersData->getData()+i);
string ipaddr = inet_ntoa(in);
uint16_t port = ntohs(*(uint16_t*)(peersData->getData()+i+4));
PeerHandle peer = new Peer(ipaddr, port, pieceLength, totalLength);
peers.push_back(peer);
}
}

View File

@ -46,21 +46,24 @@ Data::Data(const char* data, int32_t len, bool number):number(number) {
}
}
Data::Data(const string& data, bool number):number(number)
{
if(data.empty()) {
this->data = 0;
this->len = 0;
} else {
this->data = new char[data.size()];
memcpy(this->data, data.c_str(), data.size());
this->len = data.size();
}
}
Data::~Data() {
delete [] data;
}
string Data::toString() const {
if(len == 0) {
return "";
} else {
char* temp = new char[len+1];
memcpy(temp, data, len);
temp[len] = '\0';
string str(temp);
delete [] temp;
return str;
}
return string(&data[0], &data[len]);
}
const char* Data::getData() const {

View File

@ -51,6 +51,9 @@ public:
* memory of data.
*/
Data(const char* data, int32_t len, bool number = false);
Data(const string& data, bool number = false);
~Data();
string toString() const;

View File

@ -84,6 +84,7 @@ void DefaultBtContext::clear() {
numPieces = 0;
name = "";
announceTiers.clear();
_private = false;
}
void DefaultBtContext::extractPieceHash(const unsigned char* hashData,
@ -240,6 +241,12 @@ void DefaultBtContext::processMetaInfo(const MetaEntry* rootEntry, const string&
extractPieceHash((unsigned char*)pieceHashData->getData(),
pieceHashData->getLen(),
PIECE_HASH_LENGTH);
const Data* privateFlag = dynamic_cast<const Data*>(infoDic->get("private"));
if(privateFlag) {
if(privateFlag->toString() == "1") {
_private = true;
}
}
// retrieve uri-list.
// This implemantation obeys HTTP-Seeding specification:
// see http://www.getright.com/seedtorrent.html

View File

@ -43,9 +43,15 @@
#include "BtRequestMessage.h"
#include "BtPieceMessage.h"
#include "DlAbortEx.h"
#include "BtExtendedMessage.h"
#include "HandshakeExtensionMessage.h"
#include "UTPexExtensionMessage.h"
#include "DefaultExtensionMessageFactory.h"
#include "BtRegistry.h"
void DefaultBtInteractive::initiateHandshake() {
BtMessageHandle message = messageFactory->createHandshakeMessage(btContext->getInfoHash(),
BtHandshakeMessageHandle message =
messageFactory->createHandshakeMessage(btContext->getInfoHash(),
btContext->getPeerId());
dispatcher->addMessageToQueue(message);
dispatcher->sendMessages();
@ -58,6 +64,18 @@ BtMessageHandle DefaultBtInteractive::receiveHandshake(bool quickReply) {
return 0;
}
peer->setPeerId(message->getPeerId());
if(message->isFastExtensionSupported()) {
peer->setFastExtensionEnabled(true);
logger->info(MSG_FAST_EXTENSION_ENABLED, cuid);
}
if(message->isExtendedMessagingEnabled()) {
peer->setExtendedMessagingEnabled(true);
PEER_OBJECT(btContext, peer)->extensionMessageFactory =
new DefaultExtensionMessageFactory(btContext, peer);
logger->info(MSG_EXTENDED_MESSAGING_ENABLED, cuid);
}
logger->info(MSG_RECEIVE_PEER_MESSAGE, cuid,
peer->ipaddr.c_str(), peer->port,
message->toString().c_str());
@ -73,11 +91,28 @@ void DefaultBtInteractive::doPostHandshakeProcessing() {
haveCheckPoint.reset();
keepAliveCheckPoint.reset();
floodingCheckPoint.reset();
_pexCheckPoint.setTimeInSec(0);
if(peer->isExtendedMessagingEnabled()) {
addHandshakeExtendedMessageToQueue();
}
addBitfieldMessageToQueue();
addAllowedFastMessageToQueue();
sendPendingMessage();
}
void DefaultBtInteractive::addHandshakeExtendedMessageToQueue()
{
HandshakeExtensionMessageHandle m = new HandshakeExtensionMessage();
m->setClientVersion("aria2");
m->setTCPPort(btRuntime->getListenPort());
m->setExtensions(btRuntime->getExtensions());
BtExtendedMessageHandle msg =
messageFactory->createBtExtendedMessage(m);
dispatcher->addMessageToQueue(msg);
}
void DefaultBtInteractive::addBitfieldMessageToQueue() {
if(peer->isFastExtensionEnabled()) {
if(pieceStorage->allDownloadFinished()) {
@ -283,6 +318,45 @@ void DefaultBtInteractive::checkActiveInteraction()
}
}
void DefaultBtInteractive::addPeerExchangeMessage()
{
time_t interval = 60;
if(_pexCheckPoint.elapsed(interval)) {
UTPexExtensionMessageHandle m =
new UTPexExtensionMessage(peer->getExtensionMessageID("ut_pex"));
const Peers& peers = peerStorage->getPeers();
{
size_t max = 30;
for(Peers::const_iterator i = peers.begin();
i != peers.end() && max; ++i) {
const PeerHandle& cpeer = *i;
if(peer->ipaddr != cpeer->ipaddr &&
!cpeer->getFirstContactTime().elapsed(interval) &&
Util::isNumbersAndDotsNotation(cpeer->ipaddr)) {
m->addFreshPeer(cpeer);
--max;
}
}
}
{
size_t max = 10;
for(Peers::const_reverse_iterator i = peers.rbegin();
i != peers.rend() && max; ++i) {
const PeerHandle& cpeer = *i;
if(peer->ipaddr != cpeer->ipaddr &&
!cpeer->getBadConditionStartTime().elapsed(interval) &&
Util::isNumbersAndDotsNotation(cpeer->ipaddr)) {
m->addDroppedPeer(cpeer);
--max;
}
}
}
BtExtendedMessageHandle msg = messageFactory->createBtExtendedMessage(m);
dispatcher->addMessageToQueue(msg);
_pexCheckPoint.reset();
}
}
void DefaultBtInteractive::doInteractionProcessing() {
checkActiveInteraction();
@ -304,5 +378,10 @@ void DefaultBtInteractive::doInteractionProcessing() {
if(!pieceStorage->downloadFinished()) {
addRequests();
}
if(peer->getExtensionMessageID("ut_pex") && _utPexEnabled) {
addPeerExchangeMessage();
}
sendPendingMessage();
}

View File

@ -102,13 +102,16 @@ private:
Time floodingCheckPoint;
FloodingStat floodingStat;
Time inactiveCheckPoint;
Time _pexCheckPoint;
int32_t keepAliveInterval;
int32_t maxDownloadSpeedLimit;
bool _utPexEnabled;
static const int32_t FLOODING_CHECK_INTERVAL = 5;
void addBitfieldMessageToQueue();
void addAllowedFastMessageToQueue();
void addHandshakeExtendedMessageToQueue();
void decideChoking();
void checkHave();
void sendKeepAlive();
@ -117,6 +120,7 @@ private:
void addRequests();
void detectMessageFlooding();
void checkActiveInteraction();
void addPeerExchangeMessage();
public:
DefaultBtInteractive():peer(0),
@ -131,7 +135,8 @@ public:
logger(LogFactory::getInstance()),
allowedFastSetSize(10),
keepAliveInterval(120),
maxDownloadSpeedLimit(0)
maxDownloadSpeedLimit(0),
_utPexEnabled(false)
{}
virtual ~DefaultBtInteractive() {}
@ -202,6 +207,11 @@ public:
void setBtMessageFactory(const BtMessageFactoryWeakHandle& factory) {
this->messageFactory = factory;
}
void setUTPexEnabled(bool f)
{
_utPexEnabled = f;
}
};
typedef SharedHandle<DefaultBtInteractive> DefaultBtInteractiveHandle;

View File

@ -61,6 +61,8 @@
#include "BtAllowedFastMessageValidator.h"
#include "BtHandshakeMessage.h"
#include "BtHandshakeMessageValidator.h"
#include "BtExtendedMessage.h"
#include "ExtensionMessage.h"
BtMessageHandle
DefaultBtMessageFactory::createBtMessage(const unsigned char* data, int32_t dataLength)
@ -161,6 +163,14 @@ DefaultBtMessageFactory::createBtMessage(const unsigned char* data, int32_t data
msg = temp;
break;
}
case BtExtendedMessage::ID: {
if(peer->isExtendedMessagingEnabled()) {
msg = BtExtendedMessage::create(btContext, peer, (const char*)data, dataLength);
} else {
throw new DlAbortEx("Received extended message from peer during a session with extended messaging disabled.");
}
break;
}
default:
throw new DlAbortEx("Invalid message ID. id=%d", id);
}
@ -349,3 +359,11 @@ DefaultBtMessageFactory::createAllowedFastMessage(int32_t index)
setCommonProperty(msg);
return msg;
}
BtMessageHandle
DefaultBtMessageFactory::createBtExtendedMessage(const ExensionMessageHandle& msg)
{
BtExtendedMessageHandle m = new BtExtendedMessage(msg);
setCommonProperty(m);
return m;
}

View File

@ -110,6 +110,8 @@ public:
virtual BtMessageHandle createAllowedFastMessage(int32_t index);
virtual BtMessageHandle createBtExtendedMessage(const ExensionMessageHandle& msg);
void setPeer(const PeerHandle& peer) {
this->peer = peer;
}

View File

@ -53,14 +53,7 @@ BtMessageHandle DefaultBtMessageReceiver::receiveHandshake(bool quickReply) {
}
BtHandshakeMessageHandle msg = messageFactory->createHandshakeMessage(data, dataLength);
Errors errors;
if(msg->validate(errors)) {
if(msg->isFastExtensionSupported()) {
peer->setFastExtensionEnabled(true);
logger->info(MSG_FAST_EXTENSION_ENABLED, cuid);
}
} else {
// TODO throw exception here based on errors
}
msg->validate(errors);
return msg;
}

View File

@ -0,0 +1,93 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "DefaultExtensionMessageFactory.h"
#include "BtContext.h"
#include "Peer.h"
#include "DlAbortEx.h"
#include "HandshakeExtensionMessage.h"
#include "UTPexExtensionMessage.h"
#include "LogFactory.h"
#include "BtRegistry.h"
DefaultExtensionMessageFactory::DefaultExtensionMessageFactory():
_btContext(0),
_peer(0),
_logger(LogFactory::getInstance()) {}
DefaultExtensionMessageFactory::DefaultExtensionMessageFactory(const BtContextHandle& btContext,
const PeerHandle& peer):
_btContext(btContext),
_peer(peer),
_logger(LogFactory::getInstance()) {}
DefaultExtensionMessageFactory::~DefaultExtensionMessageFactory() {}
ExtensionMessageHandle
DefaultExtensionMessageFactory::createMessage(const char* data, size_t length)
{
uint8_t extensionMessageID = *data;
if(extensionMessageID == 0) {
// handshake
HandshakeExtensionMessageHandle m = HandshakeExtensionMessage::create(data, length);
m->setBtContext(_btContext);
m->setPeer(_peer);
return m;
} else {
string extensionName = BT_RUNTIME(_btContext)->getExtensionName(extensionMessageID);
if(extensionName.empty()) {
throw new DlAbortEx("No extension registered for extended message ID %u",
extensionMessageID);
}
if(extensionName == "ut_pex") {
// uTorrent compatible Peer-Exchange
UTPexExtensionMessageHandle m =
UTPexExtensionMessage::create(_btContext, data, length);
m->setBtContext(_btContext);
return m;
} else {
throw new DlAbortEx("Unsupported extension message received. extensionMessageID=%u, extensionName=%s", extensionMessageID, extensionName.c_str());
}
}
}
void DefaultExtensionMessageFactory::setBtContext(const BtContextHandle& btContext)
{
_btContext = btContext;
}
void DefaultExtensionMessageFactory::setPeer(const PeerHandle& peer)
{
_peer = peer;
}

View File

@ -0,0 +1,70 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_DEFAULT_EXTENSION_MESSAGE_FACTORY_H_
#define _D_DEFAULT_EXTENSION_MESSAGE_FACTORY_H_
#include "ExtensionMessageFactory.h"
class BtContext;
typedef SharedHandle<BtContext> BtContextHandle;
class Peer;
typedef SharedHandle<Peer> PeerHandle;
class Logger;
class DefaultExtensionMessageFactory:public ExtensionMessageFactory {
private:
BtContextHandle _btContext;
PeerHandle _peer;
const Logger* _logger;
public:
DefaultExtensionMessageFactory();
DefaultExtensionMessageFactory(const BtContextHandle& btContext,
const PeerHandle& peer);
virtual ~DefaultExtensionMessageFactory();
virtual ExtensionMessageHandle createMessage(const char* data, size_t length);
void setBtContext(const BtContextHandle& btContext);
void setPeer(const PeerHandle& peer);
};
typedef SharedHandle<DefaultExtensionMessageFactory> DefaultExtensionMessageFactoryHandle;
#endif // _D_DEFAULT_EXTENSION_MESSAGE_FACTORY_H_

View File

@ -52,30 +52,35 @@ DefaultPeerStorage::DefaultPeerStorage(BtContextHandle btContext,
DefaultPeerStorage::~DefaultPeerStorage() {}
bool DefaultPeerStorage::isPeerAlreadyAdded(const PeerHandle& peer)
{
return find(peers.begin(), peers.end(), peer) != peers.end() ||
find(incomingPeers.begin(), incomingPeers.end(), peer) != incomingPeers.end();
}
bool DefaultPeerStorage::addPeer(const PeerHandle& peer) {
Peers::iterator itr = find(peers.begin(), peers.end(), peer);
if(itr == peers.end()) {
if(isPeerAlreadyAdded(peer)) {
logger->debug("Adding %s:%u is rejected because it is already in PeerStorage.", peer->ipaddr.c_str(), peer->port);
return false;
} else {
if(peers.size() >= (size_t)maxPeerListSize) {
deleteUnusedPeer(peers.size()-maxPeerListSize+1);
}
peers.push_front(peer);
return true;
} else {
const PeerHandle& peer = *itr;
if(!peer->isGood() || peer->cuid != 0) {
return false;
} else {
*itr = peer;
return true;
}
}
}
bool DefaultPeerStorage::addIncomingPeer(const PeerHandle& peer)
{
if(isPeerAlreadyAdded(peer)) {
logger->debug("Adding %s:%u is rejected because it is already in PeerStorage.", peer->ipaddr.c_str(), peer->port);
return false;
} else {
incomingPeers.push_back(peer);
return true;
}
}
void DefaultPeerStorage::addPeer(const Peers& peers) {
for(Peers::const_iterator itr = peers.begin();

View File

@ -55,6 +55,8 @@ private:
BtRuntimeHandle btRuntime;
int64_t removedPeerSessionDownloadLength;
int64_t removedPeerSessionUploadLength;
bool isPeerAlreadyAdded(const PeerHandle& peer);
public:
DefaultPeerStorage(BtContextHandle btContext, const Option* option);
virtual ~DefaultPeerStorage();

57
src/ExtensionMessage.h Normal file
View File

@ -0,0 +1,57 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_EXTENSION_MESSAGE_H_
#define _D_EXTENSION_MESSAGE_H_
#include "common.h"
class ExtensionMessage {
public:
virtual ~ExtensionMessage() {}
virtual string getBencodedData() = 0;
virtual uint8_t getExtensionMessageID() = 0;
virtual const string& getExtensionName() const = 0;
virtual string toString() const = 0;
virtual void doReceivedAction() = 0;
};
typedef SharedHandle<ExtensionMessage> ExtensionMessageHandle;
#endif // _D_EXTENSION_MESSAGE_H_

View File

@ -0,0 +1,51 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_EXTENSION_MESSAGE_FACTORY_H_
#define _D_EXTENSION_MESSAGE_FACTORY_H_
#include "common.h"
class ExtensionMessage;
typedef SharedHandle<ExtensionMessage> ExtensionMessageHandle;
class ExtensionMessageFactory {
public:
virtual ~ExtensionMessageFactory() {}
virtual ExtensionMessageHandle createMessage(const char* data, size_t length) = 0;
};
typedef SharedHandle<ExtensionMessageFactory> ExtensionMessageFactoryHandle;
#endif // _D_EXTENSION_MESSAGE_FACTORY_H_

View File

@ -0,0 +1,174 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "HandshakeExtensionMessage.h"
#include "Peer.h"
#include "BtContext.h"
#include "Dictionary.h"
#include "Data.h"
#include "Util.h"
#include "BencodeVisitor.h"
#include "BtRegistry.h"
#include "MetaFileUtil.h"
#include "DlAbortEx.h"
#include "LogFactory.h"
#include "message.h"
const string HandshakeExtensionMessage::EXTENSION_NAME = "handshake";
HandshakeExtensionMessage::HandshakeExtensionMessage():_tcpPort(0),
_btContext(0),
_peer(0),
_logger(LogFactory::getInstance())
{}
HandshakeExtensionMessage::~HandshakeExtensionMessage() {}
string HandshakeExtensionMessage::getBencodedData()
{
SharedHandle<Dictionary> dic = new Dictionary();
if(!_clientVersion.empty()) {
Data* v = new Data(_clientVersion);
dic->put("v", v);
}
if(_tcpPort > 0) {
string portStr = Util::itos(_tcpPort);
Data* p = new Data(portStr, true);
dic->put("p", p);
}
Dictionary* exts = new Dictionary();
dic->put("m", exts);
for(map<string, uint8_t>::const_iterator itr = _extensions.begin();
itr != _extensions.end(); ++itr) {
const map<string, uint8_t>::value_type& vt = *itr;
string idStr = Util::uitos((uint32_t)vt.second);
exts->put(vt.first, new Data(idStr, true));
}
BencodeVisitor v;
dic->accept(&v);
return v.getBencodedData();
}
string HandshakeExtensionMessage::toString() const
{
string s = getExtensionName();
if(!_clientVersion.empty()) {
s += " client="+Util::urlencode(_clientVersion);
}
if(_tcpPort > 0) {
s += ", tcpPort="+Util::itos(_tcpPort);
}
for(map<string, uint8_t>::const_iterator itr = _extensions.begin();
itr != _extensions.end(); ++itr) {
const map<string, uint8_t>::value_type& vt = *itr;
s += ", "+vt.first+"="+Util::uitos((uint32_t)vt.second);
}
return s;
}
void HandshakeExtensionMessage::doReceivedAction()
{
if(_tcpPort > 0) {
_peer->port = _tcpPort;
}
for(map<string, uint8_t>::const_iterator itr = _extensions.begin();
itr != _extensions.end(); ++itr) {
const map<string, uint8_t>::value_type& vt = *itr;
_peer->setExtension(vt.first, vt.second);
}
if(_peer->port > 0) {
// This is needed when _peer is a connection initiator, listen port of
// _peer is now available, which is initially unknown.
// If _peer is a receiver or already its port is known, _peer has to be
// already added to PeerStorage using addPeer() and call
// PeerStorage::addPeer() here does nothing and just returns false.
PEER_STORAGE(_btContext)->addPeer(_peer);
}
}
void HandshakeExtensionMessage::setPeer(const PeerHandle& peer)
{
_peer = peer;
}
void HandshakeExtensionMessage::setBtContext(const BtContextHandle& btContext)
{
_btContext = btContext;
}
uint8_t HandshakeExtensionMessage::getExtensionMessageID(const string& name) const
{
map<string, uint8_t>::const_iterator i = _extensions.find(name);
if(i == _extensions.end()) {
return 0;
} else {
return (*i).second;
}
}
HandshakeExtensionMessageHandle
HandshakeExtensionMessage::create(const char* data, size_t length)
{
if(length < 1) {
throw new DlAbortEx(MSG_TOO_SMALL_PAYLOAD_SIZE,
EXTENSION_NAME.c_str(), length);
}
HandshakeExtensionMessageHandle msg = new HandshakeExtensionMessage();
msg->_logger->debug("Creating HandshakeExtensionMessage from %s",
Util::urlencode((const unsigned char*)data, length).c_str());
SharedHandle<MetaEntry> root = MetaFileUtil::bdecoding(data+1, length-1);
Dictionary* d = dynamic_cast<Dictionary*>(root.get());
if(d == 0) {
throw new DlAbortEx("Unexpected payload format for extended message handshake");
}
const Data* p = dynamic_cast<const Data*>(d->get("p"));
if(p) {
msg->_tcpPort = p->toInt();
}
const Data* v = dynamic_cast<const Data*>(d->get("v"));
if(v) {
msg->_clientVersion = v->toString();
}
const Dictionary* m = dynamic_cast<const Dictionary*>(d->get("m"));
if(m) {
const Order& order = m->getOrder();
for(Order::const_iterator i = order.begin(); i != order.end(); ++i) {
const Data* e = dynamic_cast<const Data*>(m->get(*i));
if(e) {
msg->_extensions[*i] = e->toInt();
}
}
}
return msg;
}

View File

@ -0,0 +1,128 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_HANDSHAKE_EXTENSION_MESSAGE_H_
#define _D_HANDSHAKE_EXTENSION_MESSAGE_H_
#include "ExtensionMessage.h"
#include "BtConstants.h"
class BtContext;
typedef SharedHandle<BtContext> BtContextHandle;
class Peer;
typedef SharedHandle<Peer> PeerHandle;
class HandshakeExtensionMessage;
typedef SharedHandle<HandshakeExtensionMessage> HandshakeExtensionMessageHandle;
class Logger;
class HandshakeExtensionMessage:public ExtensionMessage {
private:
string _clientVersion;
uint16_t _tcpPort;
map<string, uint8_t> _extensions;
BtContextHandle _btContext;
PeerHandle _peer;
const Logger* _logger;
public:
HandshakeExtensionMessage();
virtual ~HandshakeExtensionMessage();
virtual string getBencodedData();
virtual uint8_t getExtensionMessageID()
{
return 0;
}
virtual const string& getExtensionName() const
{
return EXTENSION_NAME;
}
static const string EXTENSION_NAME;
virtual string toString() const;
virtual void doReceivedAction();
void setClientVersion(const string& version)
{
_clientVersion = version;
}
const string& getClientVersion() const
{
return _clientVersion;
}
void setTCPPort(uint16_t port)
{
_tcpPort = port;
}
uint16_t getTCPPort() const
{
return _tcpPort;
}
void setExtension(const string& name, uint8_t id)
{
_extensions[name] = id;
}
void setExtensions(const Extensions& extensions)
{
_extensions = extensions;
}
uint8_t getExtensionMessageID(const string& name) const;
void setPeer(const PeerHandle& peer);
void setBtContext(const BtContextHandle& btContext);
static HandshakeExtensionMessageHandle create(const char* data,
size_t dataLength);
};
typedef SharedHandle<HandshakeExtensionMessage> HandshakeExtensionMessageHandle;
#endif // _D_HANDSHAKE_EXTENSION_MESSAGE_H_

View File

@ -167,6 +167,7 @@ SRCS += MetaEntry.h\
MetaFileUtil.cc MetaFileUtil.h\
MetaEntryVisitor.h\
ShaVisitor.cc ShaVisitor.h\
BencodeVisitor.cc\
PeerMessageUtil.cc PeerMessageUtil.h\
PeerAbstractCommand.cc PeerAbstractCommand.h\
PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
@ -248,7 +249,11 @@ SRCS += MetaEntry.h\
BtSetup.cc BtSetup.h\
BtFileAllocationEntry.cc BtFileAllocationEntry.h\
BtPostDownloadHandler.cc BtPostDownloadHandler.h\
BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h
BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h\
BtExtendedMessage.cc\
DefaultExtensionMessageFactory.cc\
HandshakeExtensionMessage.cc\
UTPexExtensionMessage.cc
endif # ENABLE_BITTORRENT
if ENABLE_METALINK

View File

@ -54,6 +54,7 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.cc MetaFileUtil.h\
@ENABLE_BITTORRENT_TRUE@ MetaEntryVisitor.h\
@ENABLE_BITTORRENT_TRUE@ ShaVisitor.cc ShaVisitor.h\
@ENABLE_BITTORRENT_TRUE@ BencodeVisitor.cc\
@ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.cc PeerMessageUtil.h\
@ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.cc PeerAbstractCommand.h\
@ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.cc PeerInitiateConnectionCommand.h\
@ -135,7 +136,11 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ BtSetup.cc BtSetup.h\
@ENABLE_BITTORRENT_TRUE@ BtFileAllocationEntry.cc BtFileAllocationEntry.h\
@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandler.cc BtPostDownloadHandler.h\
@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h
@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h\
@ENABLE_BITTORRENT_TRUE@ BtExtendedMessage.cc\
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactory.cc\
@ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessage.cc\
@ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessage.cc
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
@ -303,8 +308,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
MessageDigestHelper.h MetaEntry.h Data.cc Data.h Dictionary.cc \
Dictionary.h List.cc List.h MetaFileUtil.cc MetaFileUtil.h \
MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \
PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
BencodeVisitor.cc PeerMessageUtil.cc PeerMessageUtil.h \
PeerAbstractCommand.cc PeerAbstractCommand.h \
PeerInitiateConnectionCommand.cc \
PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
PeerInteractionCommand.h PeerListenCommand.cc \
PeerListenCommand.h RequestSlot.cc RequestSlot.h Directory.cc \
@ -355,8 +361,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
PeerReceiveHandshakeCommand.h BtSetup.cc BtSetup.h \
BtFileAllocationEntry.cc BtFileAllocationEntry.h \
BtPostDownloadHandler.cc BtPostDownloadHandler.h \
BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h Metalinker.cc \
Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
BtCheckIntegrityEntry.cc BtCheckIntegrityEntry.h \
BtExtendedMessage.cc DefaultExtensionMessageFactory.cc \
HandshakeExtensionMessage.cc UTPexExtensionMessage.cc \
Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
MetalinkProcessorFactory.cc MetalinkParserController.cc \
MetalinkParserStateMachine.cc InitialMetalinkParserState.cc \
@ -385,6 +393,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ ShaVisitor.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BencodeVisitor.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerMessageUtil.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerAbstractCommand.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ PeerInitiateConnectionCommand.$(OBJEXT) \
@ -433,7 +442,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ BtSetup.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtFileAllocationEntry.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandler.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.$(OBJEXT)
@ENABLE_BITTORRENT_TRUE@ BtCheckIntegrityEntry.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtExtendedMessage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactory.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessage.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessage.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
@ -935,6 +948,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AutoSaveCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeVisitor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldMan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessage.Po@am__quote@
@ -944,6 +958,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtChokeMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtContextAwareCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtDependency.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtExtendedMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtFileAllocationEntry.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHandshakeMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveAllMessage.Po@am__quote@
@ -987,6 +1002,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtRequestFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultExtensionMessageFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorage.Po@am__quote@
@ -1022,6 +1038,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelRequestCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpTunnelResponseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegment.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeExtensionMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HashMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HaveEraseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpConnection.Po@am__quote@
@ -1111,6 +1128,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransferStat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/URLMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnknownLengthPieceStorage.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParser.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@

View File

@ -49,4 +49,5 @@ public:
};
typedef SharedHandle<MetaEntry> MetaEntryHandle;
#endif // _D_META_ENTRY_H_

View File

@ -83,7 +83,7 @@ MetaEntry* MetaFileUtil::bdecoding(const char* buf, int32_t len) {
MetaEntry* MetaFileUtil::bdecodingR(const char** pp, const char* end) {
if(*pp >= end) {
throw new DlAbortEx("mulformed metainfo");
throw new DlAbortEx("Malformed metainfo");
}
MetaEntry* e;
switch(**pp) {
@ -107,7 +107,7 @@ MetaEntry* MetaFileUtil::bdecodingR(const char** pp, const char* end) {
Dictionary* MetaFileUtil::parseDictionaryTree(const char** pp, const char* end) {
if(*pp >= end) {
throw new DlAbortEx("mulformed metainfo");
throw new DlAbortEx("Malformed metainfo");
}
Dictionary* dic = new Dictionary();
try {
@ -129,7 +129,7 @@ Dictionary* MetaFileUtil::parseDictionaryTree(const char** pp, const char* end)
List* MetaFileUtil::parseListTree(const char** pp, const char* end) {
if(*pp >= end) {
throw new DlAbortEx("mulformed metainfo");
throw new DlAbortEx("Malformed metainfo");
}
List* lis = new List();
try {
@ -150,12 +150,12 @@ List* MetaFileUtil::parseListTree(const char** pp, const char* end) {
Data* MetaFileUtil::decodeInt(const char** pp, const char* end) {
if(*pp >= end) {
throw new DlAbortEx(EX_MULFORMED_META_INFO);
throw new DlAbortEx(EX_MALFORMED_META_INFO);
}
char* endTerm = (char*)memchr(*pp, 'e', end-*pp);
// TODO if endTerm is null
if(endTerm == NULL) {
throw new DlAbortEx(EX_MULFORMED_META_INFO);
throw new DlAbortEx(EX_MALFORMED_META_INFO);
}
int32_t numSize = endTerm-*pp;
@ -166,12 +166,12 @@ Data* MetaFileUtil::decodeInt(const char** pp, const char* end) {
Data* MetaFileUtil::decodeWord(const char** pp, const char* end) {
if(*pp >= end) {
throw new DlAbortEx("mulformed metainfo");
throw new DlAbortEx("Malformed metainfo");
}
char* delim = (char*)memchr(*pp, ':', end-*pp);
// TODO if delim is null
if(delim == *pp || delim == NULL) {
throw new DlAbortEx(EX_MULFORMED_META_INFO);
throw new DlAbortEx(EX_MALFORMED_META_INFO);
}
int32_t numSize = delim-*pp;
char* temp = new char[numSize+1];
@ -181,12 +181,12 @@ Data* MetaFileUtil::decodeWord(const char** pp, const char* end) {
int32_t size = strtol(temp, &endptr, 10);
if(*endptr != '\0') {
delete [] temp;
throw new DlAbortEx(EX_MULFORMED_META_INFO);
throw new DlAbortEx(EX_MALFORMED_META_INFO);
}
delete [] temp;
if(delim+1+size > end) {
throw new DlAbortEx(EX_MULFORMED_META_INFO);
throw new DlAbortEx(EX_MALFORMED_META_INFO);
}
Data* data = new Data(delim+1, size);

View File

@ -39,7 +39,7 @@
# include "MessageDigestHelper.h"
#endif // ENABLE_MESSAGE_DIGEST
Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength):
Peer::Peer(string ipaddr, uint16_t port, int32_t pieceLength, int64_t totalLength):
ipaddr(ipaddr),
port(port),
sessionUploadLength(0),
@ -113,6 +113,8 @@ void Peer::resetStatus() {
optUnchoking = false;
snubbing = false;
fastExtensionEnabled = false;
_extendedMessagingEnabled = false;
_extensions.clear();
latency = DEFAULT_LATENCY;
peerAllowedIndexSet.clear();
amAllowedIndexSet.clear();
@ -158,3 +160,30 @@ bool Peer::isGood() const
{
return _badConditionStartTime.elapsed(_badConditionInterval);
}
uint8_t Peer::getExtensionMessageID(const string& name)
{
Extensions::const_iterator itr = _extensions.find(name);
if(itr == _extensions.end()) {
return 0;
} else {
return (*itr).second;
}
}
string Peer::getExtensionName(uint8_t id)
{
for(Extensions::const_iterator itr = _extensions.begin();
itr != _extensions.end(); ++itr) {
const Extensions::value_type& p = *itr;
if(p.second == id) {
return p.first;
}
}
return "";
}
void Peer::setExtension(const string& name, uint8_t id)
{
_extensions[name] = id;
}

View File

@ -39,6 +39,7 @@
#include "BitfieldMan.h"
#include "PeerStat.h"
#include "TimeA2.h"
#include "BtConstants.h"
#include <string.h>
#define PEER_ID_LENGTH 20
@ -49,7 +50,7 @@ class Peer {
friend bool operator!=(const Peer& p1, const Peer& p2);
public:
string ipaddr;
int32_t port;
uint16_t port;
bool amChoking;
bool amInterested;
bool peerChoking;
@ -67,6 +68,8 @@ private:
Integers peerAllowedIndexSet;
// fast index set which localhost has sent to a peer.
Integers amAllowedIndexSet;
bool _extendedMessagingEnabled;
Extensions _extensions;
PeerStat peerStat;
int64_t sessionUploadLength;
int64_t sessionDownloadLength;
@ -74,10 +77,11 @@ private:
int32_t latency;
bool active;
string id;
Time _firstContactTime;
Time _badConditionStartTime;
int32_t _badConditionInterval;
public:
Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength);
Peer(string ipaddr, uint16_t port, int32_t pieceLength, int64_t totalLength);
~Peer() {
delete bitfield;
@ -193,6 +197,16 @@ public:
void addAmAllowedIndex(int32_t index);
bool isInAmAllowedIndexSet(int32_t index) const;
void setExtendedMessagingEnabled(bool enabled)
{
_extendedMessagingEnabled = enabled;
}
bool isExtendedMessagingEnabled() const
{
return _extendedMessagingEnabled;
}
bool shouldBeChoking() const;
bool hasPiece(int32_t index) const;
@ -211,6 +225,22 @@ public:
bool isGood() const;
void reconfigure(int32_t pieceLength, int64_t totalLength);
Time getFirstContactTime() const
{
return _firstContactTime;
}
Time getBadConditionStartTime() const
{
return _badConditionStartTime;
}
uint8_t getExtensionMessageID(const string& name);
string getExtensionName(uint8_t id);
void setExtension(const string& name, uint8_t id);
};
typedef SharedHandle<Peer> PeerHandle;

View File

@ -112,6 +112,9 @@ PeerInteractionCommand::PeerInteractionCommand(int32_t cuid,
btInteractive->setKeepAliveInterval(e->option->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL));
btInteractive->setMaxDownloadSpeedLimit(e->option->getAsInt(PREF_MAX_DOWNLOAD_LIMIT));
btInteractive->setBtMessageFactory(factory);
if(!btContext->isPrivate() && e->option->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) {
btInteractive->setUTPexEnabled(true);
}
this->btInteractive = btInteractive;
// reverse depends

View File

@ -125,3 +125,17 @@ void PeerMessageUtil::createPeerMessageString(unsigned char* msg,
setIntParam(msg, payloadLength);
msg[4] = messageId;
}
bool PeerMessageUtil::createcompact(char* compact, const string& addr, uint16_t port)
{
struct in_addr in;
if(inet_aton(addr.c_str(), &in) == 0) {
return false;
}
uint32_t* addrp = (uint32_t*)compact;
*addrp = in.s_addr;
uint16_t* portp = (uint16_t*)(compact+4);
*portp = htons(port);
return true;
}

View File

@ -65,6 +65,16 @@ public:
int32_t msgLength,
int32_t payloadLength,
int8_t messageId);
/**
* Creates compact tracker format(6bytes for ipv4 address and port)
* and stores the results in compact.
* compact must be at least 6 bytes and pre-allocated.
* Returns true if creation is successful, otherwise returns false.
* The example of failure reason is that addr is not numbers-and-dots
* notation.
*/
static bool createcompact(char* compact, const string& addr, uint16_t port);
};
#endif // _D_PEER_MESSAGE_UTIL_H_

View File

@ -41,6 +41,7 @@
#include "BtMessageDispatcher.h"
#include "PeerConnection.h"
#include "BtMessageReceiver.h"
#include "ExtensionMessageFactory.h"
class PeerObject {
public:
@ -48,13 +49,15 @@ public:
btRequestFactory(0),
btMessageDispatcher(0),
btMessageReceiver(0),
peerConnection(0) {}
peerConnection(0),
extensionMessageFactory(0) {}
BtMessageFactoryHandle btMessageFactory;
BtRequestFactoryHandle btRequestFactory;
BtMessageDispatcherHandle btMessageDispatcher;
BtMessageReceiverHandle btMessageReceiver;
PeerConnectionHandle peerConnection;
ExtensionMessageFactoryHandle extensionMessageFactory;
};
typedef SharedHandle<PeerObject> PeerObjectHandle;

View File

@ -77,7 +77,7 @@ bool PeerReceiveHandshakeCommand::executeInternal()
if(!PIECE_STORAGE(btContext)->downloadFinished() && tstat.getDownloadSpeed() < _lowestSpeedLimit ||
BT_RUNTIME(btContext)->getConnections() < MAX_PEERS) {
peer->reconfigure(btContext->getPieceLength(), btContext->getTotalLength());
PEER_STORAGE(btContext)->addIncomingPeer(peer);
if(PEER_STORAGE(btContext)->addIncomingPeer(peer)) {
peer->cuid = cuid;
@ -93,6 +93,7 @@ bool PeerReceiveHandshakeCommand::executeInternal()
e->commands.push_back(command);
logger->debug(MSG_INCOMING_PEER_CONNECTION, cuid, peer->cuid);
}
}
return true;
} else {
e->commands.push_back(this);

View File

@ -0,0 +1,149 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "UTPexExtensionMessage.h"
#include "Peer.h"
#include "BtContext.h"
#include "Dictionary.h"
#include "Data.h"
#include "BencodeVisitor.h"
#include "a2netcompat.h"
#include "Util.h"
#include "PeerMessageUtil.h"
#include "BtRegistry.h"
#include "CompactPeerListProcessor.h"
#include "MetaFileUtil.h"
#include "DlAbortEx.h"
#include "message.h"
const string UTPexExtensionMessage::EXTENSION_NAME = "ut_pex";
UTPexExtensionMessage::UTPexExtensionMessage(uint8_t extensionMessageID):
_extensionMessageID(extensionMessageID),
_btContext(0) {}
UTPexExtensionMessage::~UTPexExtensionMessage() {}
string UTPexExtensionMessage::getBencodedData()
{
SharedHandle<Dictionary> d = new Dictionary();
pair<string, string> freshPeerPair = createCompactPeerListAndFlag(_freshPeers);
pair<string, string> droppedPeerPair = createCompactPeerListAndFlag(_droppedPeers);
d->put("added", new Data(freshPeerPair.first));
d->put("added.f", new Data(freshPeerPair.second));
d->put("dropped", new Data(droppedPeerPair.first));
BencodeVisitor v;
d->accept(&v);
return v.getBencodedData();
}
pair<string, string> UTPexExtensionMessage::createCompactPeerListAndFlag(const Peers& peers)
{
string addrstring;
string flagstring;
for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); ++itr) {
char compact[6];
if(PeerMessageUtil::createcompact(compact, (*itr)->ipaddr, (*itr)->port)) {
addrstring.append(&compact[0], &compact[6]);
flagstring += (*itr)->isSeeder() ? "2" : "0";
}
}
return pair<string, string>(addrstring, flagstring);
}
string UTPexExtensionMessage::toString() const
{
return "ut_pex added="+Util::uitos(_freshPeers.size())+", dropped="+
Util::uitos(_droppedPeers.size());
}
void UTPexExtensionMessage::doReceivedAction()
{
PEER_STORAGE(_btContext)->addPeer(_freshPeers);
}
void UTPexExtensionMessage::addFreshPeer(const PeerHandle& peer)
{
_freshPeers.push_back(peer);
}
const Peers& UTPexExtensionMessage::getFreshPeers() const
{
return _freshPeers;
}
void UTPexExtensionMessage::addDroppedPeer(const PeerHandle& peer)
{
_droppedPeers.push_back(peer);
}
const Peers& UTPexExtensionMessage::getDroppedPeers() const
{
return _droppedPeers;
}
void UTPexExtensionMessage::setBtContext(const BtContextHandle& btContext)
{
_btContext = btContext;
}
UTPexExtensionMessageHandle
UTPexExtensionMessage::create(const BtContextHandle& btContext,
const char* data, size_t len)
{
if(len < 1) {
throw new DlAbortEx(MSG_TOO_SMALL_PAYLOAD_SIZE,
EXTENSION_NAME.c_str(), len);
}
UTPexExtensionMessageHandle msg = new UTPexExtensionMessage(*data);
SharedHandle<MetaEntry> root = MetaFileUtil::bdecoding(data+1, len-1);
if(root.isNull()) {
return msg;
}
const Dictionary* d = dynamic_cast<const Dictionary*>(root.get());
if(d) {
CompactPeerListProcessor proc(btContext->getPieceLength(),
btContext->getTotalLength());
const Data* added = dynamic_cast<const Data*>(d->get("added"));
if(added) {
msg->_freshPeers = proc.extractPeer(added);
}
const Data* dropped = dynamic_cast<const Data*>(d->get("dropped"));
if(dropped) {
msg->_droppedPeers = proc.extractPeer(dropped);
}
}
return msg;
}

View File

@ -0,0 +1,99 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_UT_PEX_EXTENSION_MESSAGE_H_
#define _D_UT_PEX_EXTENSION_MESSAGE_H_
#include "ExtensionMessage.h"
class BtContext;
typedef SharedHandle<BtContext> BtContextHandle;
class Peer;
typedef SharedHandle<Peer> PeerHandle;
typedef deque<PeerHandle> Peers;
class UTPexExtensionMessage;
typedef SharedHandle<UTPexExtensionMessage> UTPexExtensionMessageHandle;
class UTPexExtensionMessage:public ExtensionMessage {
private:
uint8_t _extensionMessageID;
Peers _freshPeers;
Peers _droppedPeers;
BtContextHandle _btContext;
pair<string, string> createCompactPeerListAndFlag(const Peers& peers);
public:
UTPexExtensionMessage(uint8_t extensionMessageID);
virtual ~UTPexExtensionMessage();
virtual string getBencodedData();
virtual uint8_t getExtensionMessageID()
{
return _extensionMessageID;
}
virtual const string& getExtensionName() const
{
return EXTENSION_NAME;
}
static const string EXTENSION_NAME;
virtual string toString() const;
virtual void doReceivedAction();
void addFreshPeer(const PeerHandle& peer);
const Peers& getFreshPeers() const;
void addDroppedPeer(const PeerHandle& peer);
const Peers& getDroppedPeers() const;
void setBtContext(const BtContextHandle& btContext);
static UTPexExtensionMessageHandle create(const BtContextHandle& btContext,
const char* data, size_t len);
};
typedef SharedHandle<UTPexExtensionMessage> UTPexExtensionMessageHandle;
#endif // _D_UT_PEX_EXTENSION_MESSAGE_H_

View File

@ -78,6 +78,7 @@
#define MSG_DELETING_REQUEST_SLOT_TIMEOUT _("CUID#%d - Deleting request slot blockIndex=%d because of time out")
#define MSG_DELETING_REQUEST_SLOT_ACQUIRED _("CUID#%d - Deleting request slot blockIndex=%d because the block has been acquired.")
#define MSG_FAST_EXTENSION_ENABLED _("CUID#%d - Fast extension enabled.")
#define MSG_EXTENDED_MESSAGING_ENABLED _("CUID#%d - Extended Messaging enabled.")
#define MSG_FILE_ALLOCATION_FAILURE _("CUID#%d - Exception caught while allocating file space.")
#define MSG_CONTENT_DISPOSITION_DETECTED _("CUID#%d - Content-Disposition detected. Use %s as filename")
#define MSG_PEER_BANNED _("CUID#%d - Peer %s:%d banned.")
@ -131,6 +132,7 @@
#define MSG_RESOURCE_NOT_FOUND _("Resource not found")
#define MSG_FILE_RENAMED _("File already exists. Renamed to %s.")
#define MSG_CANNOT_PARSE_METALINK _("Cannot parse metalink XML file. XML may be malformed.")
#define MSG_TOO_SMALL_PAYLOAD_SIZE _("Too small payload size for %s, size=%d.")
#define EX_TIME_OUT _("Timeout.")
#define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.")
@ -154,7 +156,7 @@
#define EX_AUTH_FAILED _("Authorization failed.")
#define EX_GOT_EOF _("Got EOF from the server.")
#define EX_EOF_FROM_PEER _("Got EOF from peer.")
#define EX_MULFORMED_META_INFO _("Malformed meta info.")
#define EX_MALFORMED_META_INFO _("Malformed meta info.")
#define EX_FILE_OPEN _("Failed to open the file %s, cause: %s")
#define EX_FILE_WRITE _("Failed to write into the file %s, cause: %s")

View File

@ -129,6 +129,7 @@ Option* option_processing(int argc, char* const argv[])
op->put(PREF_ENABLE_DIRECT_IO, V_FALSE);
op->put(PREF_ALLOW_PIECE_LENGTH_CHANGE, V_FALSE);
op->put(PREF_METALINK_PREFERRED_PROTOCOL, V_NONE);
op->put(PREF_ENABLE_PEER_EXCHANGE, V_TRUE);
while(1) {
int optIndex = 0;
int lopt;

View File

@ -207,6 +207,8 @@
#define PREF_BT_KEEP_ALIVE_INTERVAL "bt-keep-alive-interval"
// values: a string, less than or equals to 20 bytes length
#define PREF_PEER_ID_PREFIX "peer-id-prefix"
// values: true | false
#define PREF_ENABLE_PEER_EXCHANGE "enable-peer-exchange"
/**
* Metalink related preferences

View File

@ -0,0 +1,70 @@
#include "BencodeVisitor.h"
#include "Data.h"
#include "List.h"
#include "Dictionary.h"
#include <cppunit/extensions/HelperMacros.h>
class BencodeVisitorTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(BencodeVisitorTest);
CPPUNIT_TEST(testVisit_data);
CPPUNIT_TEST(testVisit_list);
CPPUNIT_TEST(testVisit_dictionary);
CPPUNIT_TEST_SUITE_END();
private:
public:
void setUp() {
}
void testVisit_data();
void testVisit_list();
void testVisit_dictionary();
};
CPPUNIT_TEST_SUITE_REGISTRATION( BencodeVisitorTest );
void BencodeVisitorTest::testVisit_data()
{
{
BencodeVisitor v;
string str = "apple";
MetaEntryHandle m = new Data(str.c_str(), str.size());
m->accept(&v);
CPPUNIT_ASSERT_EQUAL(string("5:apple"), v.getBencodedData());
}
{
BencodeVisitor v;
string str = "123";
MetaEntryHandle m = new Data(str.c_str(), str.size(), true);
m->accept(&v);
CPPUNIT_ASSERT_EQUAL(string("i123e"), v.getBencodedData());
}
}
void BencodeVisitorTest::testVisit_list()
{
BencodeVisitor v;
List l;
string s1 = "alpha";
l.add(new Data(s1.c_str(), s1.size()));
string s2 = "bravo";
l.add(new Data(s2.c_str(), s2.size()));
string s3 = "123";
l.add(new Data(s3.c_str(), s3.size(), true));
l.accept(&v);
CPPUNIT_ASSERT_EQUAL(string("l5:alpha5:bravoi123ee"), v.getBencodedData());
}
void BencodeVisitorTest::testVisit_dictionary()
{
BencodeVisitor v;
Dictionary d;
string s1 = "alpha";
d.put("team", new Data(s1.c_str(), s1.size()));
string s2 = "123";
d.put("score", new Data(s2.c_str(), s2.size(), true));
d.accept(&v);
CPPUNIT_ASSERT_EQUAL(string("d4:team5:alpha5:scorei123ee"), v.getBencodedData());
}

View File

@ -0,0 +1,121 @@
#include "BtExtendedMessage.h"
#include "PeerMessageUtil.h"
#include "MockBtContext.h"
#include "MockExtensionMessageFactory.h"
#include <cppunit/extensions/HelperMacros.h>
using namespace std;
class BtExtendedMessageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(BtExtendedMessageTest);
CPPUNIT_TEST(testCreate);
CPPUNIT_TEST(testGetMessage);
CPPUNIT_TEST(testDoReceivedAction);
CPPUNIT_TEST(testToString);
CPPUNIT_TEST_SUITE_END();
private:
public:
void setUp()
{
BtRegistry::unregisterAll();
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testCreate();
void testGetMessage();
void testDoReceivedAction();
void testToString();
};
CPPUNIT_TEST_SUITE_REGISTRATION(BtExtendedMessageTest);
void BtExtendedMessageTest::testCreate() {
PeerHandle peer = new Peer("192.168.0.1", 6969, 16*1024, 256*1024);
peer->setExtension("charlie", 1);
MockBtContextHandle ctx = new MockBtContext();
unsigned char infohash[20];
memset(infohash, 0, sizeof(infohash));
ctx->setInfoHash(infohash);
MockExtensionMessageFactoryHandle exmsgFactory = new MockExtensionMessageFactory();
BtRegistry::registerPeerObjectCluster(ctx->getInfoHashAsString(), new PeerObjectCluster());
PeerObjectHandle peerObject = new PeerObject();
peerObject->extensionMessageFactory = exmsgFactory;
PEER_OBJECT_CLUSTER(ctx)->registerHandle(peer->getId(), peerObject);
// payload:{4:name3:foo}->11bytes
string payload = "4:name3:foo";
char msg[17];// 6+11bytes
PeerMessageUtil::createPeerMessageString((unsigned char*)msg, sizeof(msg), 13, 20);
msg[5] = 1; // Set dummy extended message ID 1
memcpy(msg+6, payload.c_str(), payload.size());
BtExtendedMessageHandle pm = BtExtendedMessage::create(ctx,
peer,
&msg[4], 13);
CPPUNIT_ASSERT_EQUAL((int8_t)20, pm->getId());
// case: payload size is wrong
try {
char msg[5];
PeerMessageUtil::createPeerMessageString((unsigned char*)msg, sizeof(msg), 1, 20);
BtExtendedMessage::create(ctx, peer, &msg[4], 1);
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
// case: id is wrong
try {
char msg[6];
PeerMessageUtil::createPeerMessageString((unsigned char*)msg, sizeof(msg), 2, 21);
BtExtendedMessage::create(ctx, peer, &msg[4], 2);
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
}
void BtExtendedMessageTest::testGetMessage() {
string payload = "4:name3:foo";
uint8_t extendedMessageID = 1;
MockExtensionMessageHandle exmsg =
new MockExtensionMessage("charlie", extendedMessageID,
payload.c_str(),
payload.size());
BtExtendedMessage msg(exmsg);
char data[17];
PeerMessageUtil::createPeerMessageString((unsigned char*)data, sizeof(data), 13, 20);
*(data+5) = extendedMessageID;
memcpy(data+6, payload.c_str(), payload.size());
CPPUNIT_ASSERT(memcmp(msg.getMessage(), data, 17) == 0);
}
void BtExtendedMessageTest::testDoReceivedAction() {
MockExtensionMessageHandle exmsg =
new MockExtensionMessage("charlie", 1, "", 0);
BtExtendedMessage msg(exmsg);
msg.doReceivedAction();
CPPUNIT_ASSERT(exmsg->_doReceivedActionCalled);
}
void BtExtendedMessageTest::testToString() {
string payload = "4:name3:foo";
uint8_t extendedMessageID = 1;
MockExtensionMessageHandle exmsg =
new MockExtensionMessage("charlie", extendedMessageID,
payload.c_str(),
payload.size());
BtExtendedMessage msg(exmsg);
CPPUNIT_ASSERT_EQUAL(string("extended charlie"), msg.toString());
}

View File

@ -34,7 +34,7 @@ void createHandshakeMessageData(unsigned char* msg) {
msg[0] = 19;
memcpy(&msg[1], BtHandshakeMessageTest::BTPSTR.c_str(),
BtHandshakeMessageTest::BTPSTR.size());
unsigned char reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 };
unsigned char reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04 };
memcpy(&msg[20], reserved, sizeof(reserved));
unsigned char infoHash[] = { 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff,
@ -56,7 +56,7 @@ void BtHandshakeMessageTest::testCreate() {
CPPUNIT_ASSERT_EQUAL((int8_t)19, message->getPstrlen());
CPPUNIT_ASSERT_EQUAL(Util::toHex((const unsigned char*)BTPSTR.c_str(), BTPSTR.size()),
Util::toHex(message->getPstr(), BtHandshakeMessage::PSTR_LENGTH));
CPPUNIT_ASSERT_EQUAL(string("0000000000000004"),
CPPUNIT_ASSERT_EQUAL(string("0000000000100004"),
Util::toHex(message->getReserved(), BtHandshakeMessage::RESERVED_LENGTH));
CPPUNIT_ASSERT_EQUAL(string("ffffffffffffffffffffffffffffffffffffffff"),
Util::toHex(message->getInfoHash(), INFO_HASH_LENGTH));
@ -98,5 +98,5 @@ void BtHandshakeMessageTest::testToString() {
msg.setInfoHash(infoHash);
msg.setPeerId(peerId);
CPPUNIT_ASSERT_EQUAL(string("handshake peerId=%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0, reserved=0000000000000004"), msg.toString());
CPPUNIT_ASSERT_EQUAL(string("handshake peerId=%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0%f0, reserved=0000000000100004"), msg.toString());
}

View File

@ -0,0 +1,78 @@
#include "DefaultBtMessageFactory.h"
#include "Peer.h"
#include "PeerMessageUtil.h"
#include "BtRegistry.h"
#include "MockBtContext.h"
#include "MockExtensionMessageFactory.h"
#include "BtExtendedMessage.h"
#include <cppunit/extensions/HelperMacros.h>
class DefaultBtMessageFactoryTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DefaultBtMessageFactoryTest);
CPPUNIT_TEST(testCreateBtMessage_BtExtendedMessage);
CPPUNIT_TEST_SUITE_END();
private:
MockBtContextHandle _btContext;
PeerHandle _peer;
public:
DefaultBtMessageFactoryTest():_btContext(0), _peer(0) {}
void setUp()
{
BtRegistry::unregisterAll();
MockBtContextHandle btContext = new MockBtContext();
unsigned char infohash[20];
memset(infohash, 0, sizeof(infohash));
btContext->setInfoHash(infohash);
_btContext = btContext;
_peer = new Peer("192.168.0.1", 6969, 16*1024, 256*1024);
_peer->setExtendedMessagingEnabled(true);
MockExtensionMessageFactoryHandle exmsgFactory = new MockExtensionMessageFactory();
BtRegistry::registerPeerObjectCluster(_btContext->getInfoHashAsString(),
new PeerObjectCluster());
PeerObjectHandle peerObject = new PeerObject();
peerObject->extensionMessageFactory = exmsgFactory;
PEER_OBJECT_CLUSTER(_btContext)->registerHandle(_peer->getId(), peerObject);
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testCreateBtMessage_BtExtendedMessage();
};
CPPUNIT_TEST_SUITE_REGISTRATION(DefaultBtMessageFactoryTest);
void DefaultBtMessageFactoryTest::testCreateBtMessage_BtExtendedMessage()
{
DefaultBtMessageFactory factory;
factory.setBtContext(_btContext);
factory.setPeer(_peer);
// payload:{4:name3:foo}->11bytes
string payload = "4:name3:foo";
char msg[17];// 6+11bytes
PeerMessageUtil::createPeerMessageString((unsigned char*)msg, sizeof(msg), 13, 20);
msg[5] = 1; // Set dummy extended message ID 1
memcpy(msg+6, payload.c_str(), payload.size());
BtExtendedMessageHandle m = factory.createBtMessage((const unsigned char*)msg+4, sizeof(msg));
try {
// disable extended messaging
_peer->setExtendedMessagingEnabled(false);
factory.createBtMessage((const unsigned char*)msg+4, sizeof(msg));
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
}

View File

@ -0,0 +1,113 @@
#include "DefaultExtensionMessageFactory.h"
#include "Peer.h"
#include "MockBtContext.h"
#include "PeerMessageUtil.h"
#include "HandshakeExtensionMessage.h"
#include "UTPexExtensionMessage.h"
#include "Exception.h"
#include "BtRegistry.h"
#include "BtRuntime.h"
#include <cppunit/extensions/HelperMacros.h>
class DefaultExtensionMessageFactoryTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DefaultExtensionMessageFactoryTest);
CPPUNIT_TEST(testCreateMessage_unknown);
CPPUNIT_TEST(testCreateMessage_Handshake);
CPPUNIT_TEST(testCreateMessage_UTPex);
CPPUNIT_TEST_SUITE_END();
private:
MockBtContextHandle _btContext;
PeerHandle _peer;
public:
DefaultExtensionMessageFactoryTest():_btContext(0), _peer(0) {}
void setUp()
{
BtRegistry::unregisterAll();
MockBtContextHandle btContext = new MockBtContext();
unsigned char infohash[20];
memset(infohash, 0, sizeof(infohash));
btContext->setInfoHash(infohash);
_btContext = btContext;
BtRuntimeHandle btRuntime = new BtRuntime();
BtRegistry::registerBtRuntime(_btContext->getInfoHashAsString(),
btRuntime);
_peer = new Peer("192.168.0.1", 6969, 16*1024, 256*1024);
_peer->setExtension("ut_pex", 1);
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testCreateMessage_unknown();
void testCreateMessage_Handshake();
void testCreateMessage_UTPex();
};
CPPUNIT_TEST_SUITE_REGISTRATION(DefaultExtensionMessageFactoryTest);
void DefaultExtensionMessageFactoryTest::testCreateMessage_unknown()
{
DefaultExtensionMessageFactory factory;
factory.setBtContext(_btContext);
factory.setPeer(_peer);
_peer->setExtension("foo", 255);
char id[1] = { 255 };
string data = string(&id[0], &id[1]);
try {
factory.createMessage(data.c_str(), data.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
}
void DefaultExtensionMessageFactoryTest::testCreateMessage_Handshake()
{
DefaultExtensionMessageFactory factory;
factory.setBtContext(_btContext);
factory.setPeer(_peer);
char id[1] = { 0 };
string data = string(&id[0], &id[1])+"d1:v5:aria2e";
HandshakeExtensionMessageHandle m = factory.createMessage(data.c_str(), data.size());
CPPUNIT_ASSERT_EQUAL(string("aria2"), m->getClientVersion());
}
void DefaultExtensionMessageFactoryTest::testCreateMessage_UTPex()
{
DefaultExtensionMessageFactory factory;
factory.setBtContext(_btContext);
factory.setPeer(_peer);
char c1[6];
char c2[6];
char c3[6];
char c4[6];
PeerMessageUtil::createcompact(c1, "192.168.0.1", 6881);
PeerMessageUtil::createcompact(c2, "10.1.1.2", 9999);
PeerMessageUtil::createcompact(c3, "192.168.0.2", 6882);
PeerMessageUtil::createcompact(c4, "10.1.1.3",10000);
char id[1] = { BT_RUNTIME(_btContext)->getExtensionMessageID("ut_pex") };
string data = string(&id[0], &id[1])+"d5:added12:"+
string(&c1[0], &c1[6])+string(&c2[0], &c2[6])+
"7:added.f2:207:dropped12:"+
string(&c3[0], &c3[6])+string(&c4[0], &c4[6])+
"e";
UTPexExtensionMessageHandle m = factory.createMessage(data.c_str(), data.size());
CPPUNIT_ASSERT_EQUAL(BT_RUNTIME(_btContext)->getExtensionMessageID("ut_pex"),
m->getExtensionMessageID());
}

View File

@ -36,7 +36,7 @@ void DefaultPeerListProcessorTest::testExtractPeer() {
CPPUNIT_ASSERT_EQUAL((size_t)1, peers.size());
PeerHandle peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), peer->ipaddr);
CPPUNIT_ASSERT_EQUAL((int32_t)2006, peer->port);
CPPUNIT_ASSERT_EQUAL((uint16_t)2006, peer->port);
}
void DefaultPeerListProcessorTest::testExtract2Peers() {
@ -49,9 +49,9 @@ void DefaultPeerListProcessorTest::testExtract2Peers() {
CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
PeerHandle peer = *peers.begin();
CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), peer->ipaddr);
CPPUNIT_ASSERT_EQUAL((int32_t)2006, peer->port);
CPPUNIT_ASSERT_EQUAL((uint16_t)2006, peer->port);
peer = *(peers.begin()+1);
CPPUNIT_ASSERT_EQUAL(string("192.168.0.2"), peer->ipaddr);
CPPUNIT_ASSERT_EQUAL((int32_t)2007, peer->port);
CPPUNIT_ASSERT_EQUAL((uint16_t)2007, peer->port);
}

View File

@ -113,9 +113,8 @@ void DefaultPeerStorageTest::testAddPeer() {
CPPUNIT_ASSERT_EQUAL((int32_t)3, ps.countPeer());
// this is true, because peer1 in the container has no errors and
// it is replaced by peer1(self assignment).
CPPUNIT_ASSERT_EQUAL(true, ps.addPeer(peer1));
// this returns false, because peer1 is already in the container
CPPUNIT_ASSERT_EQUAL(false, ps.addPeer(peer1));
// the number of peers doesn't change.
CPPUNIT_ASSERT_EQUAL((int32_t)3, ps.countPeer());

View File

@ -0,0 +1,155 @@
#include "HandshakeExtensionMessage.h"
#include "Peer.h"
#include "MockBtContext.h"
#include "MockPeerStorage.h"
#include "BtRegistry.h"
#include <cppunit/extensions/HelperMacros.h>
class HandshakeExtensionMessageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(HandshakeExtensionMessageTest);
CPPUNIT_TEST(testGetExtensionMessageID);
CPPUNIT_TEST(testGetExtensionName);
CPPUNIT_TEST(testGetBencodedData);
CPPUNIT_TEST(testToString);
CPPUNIT_TEST(testDoReceivedAction);
CPPUNIT_TEST(testCreate);
CPPUNIT_TEST(testCreate_stringnum);
CPPUNIT_TEST_SUITE_END();
private:
BtContextHandle _btContext;
public:
HandshakeExtensionMessageTest():_btContext(0) {}
void setUp()
{
BtRegistry::unregisterAll();
MockBtContextHandle btContext = new MockBtContext();
unsigned char infohash[20];
memset(infohash, 0, sizeof(infohash));
btContext->setInfoHash(infohash);
_btContext = btContext;
MockPeerStorageHandle peerStorage = new MockPeerStorage();
BtRegistry::registerPeerStorage(_btContext->getInfoHashAsString(),
peerStorage);
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testGetExtensionMessageID();
void testGetExtensionName();
void testGetBencodedData();
void testToString();
void testDoReceivedAction();
void testCreate();
void testCreate_stringnum();
};
CPPUNIT_TEST_SUITE_REGISTRATION(HandshakeExtensionMessageTest);
void HandshakeExtensionMessageTest::testGetExtensionMessageID()
{
HandshakeExtensionMessage msg;
CPPUNIT_ASSERT_EQUAL((uint8_t)0, msg.getExtensionMessageID());
}
void HandshakeExtensionMessageTest::testGetExtensionName()
{
HandshakeExtensionMessage msg;
CPPUNIT_ASSERT_EQUAL(string("handshake"), msg.getExtensionName());
}
void HandshakeExtensionMessageTest::testGetBencodedData()
{
HandshakeExtensionMessage msg;
msg.setClientVersion("aria2");
msg.setTCPPort(6889);
msg.setExtension("ut_pex", 1);
msg.setExtension("a2_dht", 2);
CPPUNIT_ASSERT_EQUAL(string("d1:v5:aria21:pi6889e1:md6:a2_dhti2e6:ut_pexi1eee"), msg.getBencodedData());
}
void HandshakeExtensionMessageTest::testToString()
{
HandshakeExtensionMessage msg;
msg.setClientVersion("aria2");
msg.setTCPPort(6889);
msg.setExtension("ut_pex", 1);
msg.setExtension("a2_dht", 2);
CPPUNIT_ASSERT_EQUAL(string("handshake client=aria2, tcpPort=6889, a2_dht=2, ut_pex=1"), msg.toString());
}
void HandshakeExtensionMessageTest::testDoReceivedAction()
{
PeerHandle peer = new Peer("192.168.0.1", 0, 1, 1);
HandshakeExtensionMessage msg;
msg.setClientVersion("aria2");
msg.setTCPPort(6889);
msg.setExtension("ut_pex", 1);
msg.setExtension("a2_dht", 2);
msg.setPeer(peer);
msg.setBtContext(_btContext);
msg.doReceivedAction();
CPPUNIT_ASSERT_EQUAL((uint16_t)6889, peer->port);
CPPUNIT_ASSERT_EQUAL((uint8_t)1, peer->getExtensionMessageID("ut_pex"));
CPPUNIT_ASSERT_EQUAL((uint8_t)2, peer->getExtensionMessageID("a2_dht"));
CPPUNIT_ASSERT_EQUAL((size_t)1, PEER_STORAGE(_btContext)->getPeers().size());
PeerHandle p1 = PEER_STORAGE(_btContext)->getPeers().front();
CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), p1->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)6889, p1->port);
}
void HandshakeExtensionMessageTest::testCreate()
{
string in = "0d1:pi6881e1:v5:aria21:md6:ut_pexi1eee";
HandshakeExtensionMessageHandle m =
HandshakeExtensionMessage::create(in.c_str(), in.size());
CPPUNIT_ASSERT_EQUAL(string("aria2"), m->getClientVersion());
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, m->getTCPPort());
CPPUNIT_ASSERT_EQUAL((uint8_t)1, m->getExtensionMessageID("ut_pex"));
try {
// bad payload format
string in = "011:hello world";
HandshakeExtensionMessage::create(in.c_str(), in.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
try {
// malformed dencoded message
string in = "011:hello";
HandshakeExtensionMessage::create(in.c_str(), in.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
try {
// 0 length data
string in = "";
HandshakeExtensionMessage::create(in.c_str(), in.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
}
void HandshakeExtensionMessageTest::testCreate_stringnum()
{
string in = "0d1:p4:68811:v5:aria21:md6:ut_pex1:1ee";
HandshakeExtensionMessageHandle m =
HandshakeExtensionMessage::create(in.c_str(), in.size());
CPPUNIT_ASSERT_EQUAL(string("aria2"), m->getClientVersion());
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, m->getTCPPort());
CPPUNIT_ASSERT_EQUAL((uint8_t)1, m->getExtensionMessageID("ut_pex"));
}

View File

@ -95,7 +95,13 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
BtDependencyTest.cc\
BtPostDownloadHandlerTest.cc\
DownloadHandlerFactoryTest.cc\
TimeSeedCriteriaTest.cc
TimeSeedCriteriaTest.cc\
BencodeVisitorTest.cc\
BtExtendedMessageTest.cc\
HandshakeExtensionMessageTest.cc\
UTPexExtensionMessageTest.cc\
DefaultBtMessageFactoryTest.cc\
DefaultExtensionMessageFactoryTest.cc
endif # ENABLE_BITTORRENT
if ENABLE_METALINK

View File

@ -83,7 +83,13 @@ check_PROGRAMS = $(am__EXEEXT_1)
@ENABLE_BITTORRENT_TRUE@ BtDependencyTest.cc\
@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandlerTest.cc\
@ENABLE_BITTORRENT_TRUE@ DownloadHandlerFactoryTest.cc\
@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.cc
@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.cc\
@ENABLE_BITTORRENT_TRUE@ BencodeVisitorTest.cc\
@ENABLE_BITTORRENT_TRUE@ BtExtendedMessageTest.cc\
@ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessageTest.cc\
@ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessageTest.cc\
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.cc\
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.cc
@ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
@ -156,8 +162,11 @@ am__aria2c_SOURCES_DIST = AllTest.cc Base64Test.cc SequenceTest.cc \
PeerMessageUtilTest.cc ShareRatioSeedCriteriaTest.cc \
BtRegistryTest.cc BtDependencyTest.cc \
BtPostDownloadHandlerTest.cc DownloadHandlerFactoryTest.cc \
TimeSeedCriteriaTest.cc MetalinkerTest.cc MetalinkEntryTest.cc \
Metalink2RequestGroupTest.cc \
TimeSeedCriteriaTest.cc BencodeVisitorTest.cc \
BtExtendedMessageTest.cc HandshakeExtensionMessageTest.cc \
UTPexExtensionMessageTest.cc DefaultBtMessageFactoryTest.cc \
DefaultExtensionMessageFactoryTest.cc MetalinkerTest.cc \
MetalinkEntryTest.cc Metalink2RequestGroupTest.cc \
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
MetalinkParserControllerTest.cc MetalinkProcessorTest.cc
@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
@ -203,7 +212,13 @@ am__aria2c_SOURCES_DIST = AllTest.cc Base64Test.cc SequenceTest.cc \
@ENABLE_BITTORRENT_TRUE@ BtDependencyTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtPostDownloadHandlerTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DownloadHandlerFactoryTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.$(OBJEXT)
@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BencodeVisitorTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ BtExtendedMessageTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ HandshakeExtensionMessageTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ UTPexExtensionMessageTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultBtMessageFactoryTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DefaultExtensionMessageFactoryTest.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
@ -518,12 +533,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceListTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BencodeVisitorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtBitfieldMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtCancelMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtChokeMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtDependencyTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtExtendedMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHandshakeMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveAllMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtHaveMessageTest.Po@am__quote@
@ -549,9 +566,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounceTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtContextTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageDispatcherTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtMessageFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtProgressInfoFileTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtRequestFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultDiskWriterTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultExtensionMessageFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerListProcessorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPeerStorageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultPieceStorageTest.Po@am__quote@
@ -562,6 +581,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileUriListParserTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GrowSegmentTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HandshakeExtensionMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderProcessorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpRequestTest.Po@am__quote@
@ -604,6 +624,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalcTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StreamUriListParserTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@

View File

@ -3,6 +3,9 @@
#include "BtMessageFactory.h"
class ExtensionMessage;
typedef SharedHandle<ExtensionMessage> ExensionMessageHandle;
class MockBtMessageFactory : public BtMessageFactory {
public:
MockBtMessageFactory() {}
@ -84,6 +87,11 @@ public:
virtual BtMessageHandle createAllowedFastMessage(int32_t index) {
return BtMessageHandle(0);
}
virtual BtMessageHandle createBtExtendedMessage(const ExensionMessageHandle&)
{
return BtMessageHandle(0);
}
};
typedef SharedHandle<MockBtMessageFactory> MockBtMessageFactoryHandle;

View File

@ -0,0 +1,51 @@
#ifndef _D_MOCK_EXTENSION_MESSAGE_H_
#define _D_MOCK_EXTENSION_MESSAGE_H_
#include "ExtensionMessage.h"
class MockExtensionMessage:public ExtensionMessage {
public:
string _extensionName;
uint8_t _extensionMessageID;
string _data;
bool _doReceivedActionCalled;
public:
MockExtensionMessage(const string& extensionName,
uint8_t extensionMessageID,
const char* data,
size_t length):_extensionName(extensionName),
_extensionMessageID(extensionMessageID),
_data(&data[0], &data[length]),
_doReceivedActionCalled(false) {}
virtual ~MockExtensionMessage() {}
virtual string getBencodedData()
{
return _data;
}
virtual uint8_t getExtensionMessageID()
{
return _extensionMessageID;
}
virtual const string& getExtensionName() const
{
return _extensionName;
}
virtual string toString() const
{
return _extensionName;
}
virtual void doReceivedAction()
{
_doReceivedActionCalled = true;
}
};
typedef SharedHandle<MockExtensionMessage> MockExtensionMessageHandle;
#endif // _D_MOCK_EXTENSION_MESSAGE_H_

View File

@ -0,0 +1,20 @@
#ifndef _D_MOCK_EXTENSION_MESSAGE_FACTORY_H_
#define _D_MOCK_EXTENSION_MESSAGE_FACTORY_H_
#include "ExtensionMessageFactory.h"
#include "MockExtensionMessage.h"
class MockExtensionMessageFactory:public ExtensionMessageFactory {
public:
virtual ~MockExtensionMessageFactory() {}
virtual ExtensionMessageHandle createMessage(const char* data,
size_t length)
{
return new MockExtensionMessage("a2_mock", *data, data+1, length-1);
}
};
typedef SharedHandle<MockExtensionMessageFactory> MockExtensionMessageFactoryHandle;
#endif // _D_MOCK_EXTENSION_MESSAGE_FACTORY_H_

View File

@ -51,12 +51,13 @@ void ShaVisitorTest::testVisit() {
void ShaVisitorTest::testVisitCompound() {
ShaVisitor v;
MetaEntry* e = MetaFileUtil::parseMetaFile("test.torrent");
string data = "d4:name5:aria24:listli123eee";
MetaEntry* e = MetaFileUtil::bdecoding(data.c_str(), data.size());
e->accept(&v);
unsigned char md[20];
int len = 0;
v.getHash(md, len);
string hashHex = hexHash(md, len);
CPPUNIT_ASSERT_EQUAL(string("5a2bf55fb6ec71a9cd3e06537aa7795cafccffab"),
CPPUNIT_ASSERT_EQUAL(string("75538fbac9a074bb98c6a19b6bca3bc87ef9bf8e"),
hashHex);
}

View File

@ -0,0 +1,187 @@
#include "UTPexExtensionMessage.h"
#include "Peer.h"
#include "a2netcompat.h"
#include "Util.h"
#include "PeerMessageUtil.h"
#include "BtRegistry.h"
#include "MockBtContext.h"
#include "MockPeerStorage.h"
#include <cppunit/extensions/HelperMacros.h>
class UTPexExtensionMessageTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(UTPexExtensionMessageTest);
CPPUNIT_TEST(testGetExtensionMessageID);
CPPUNIT_TEST(testGetExtensionName);
CPPUNIT_TEST(testGetBencodedData);
CPPUNIT_TEST(testToString);
CPPUNIT_TEST(testDoReceivedAction);
CPPUNIT_TEST(testCreate);
CPPUNIT_TEST_SUITE_END();
private:
MockBtContextHandle _btContext;
public:
UTPexExtensionMessageTest():_btContext(0) {}
void setUp()
{
BtRegistry::unregisterAll();
MockBtContextHandle btContext = new MockBtContext();
unsigned char infohash[20];
memset(infohash, 0, sizeof(infohash));
btContext->setInfoHash(infohash);
_btContext = btContext;
MockPeerStorageHandle peerStorage = new MockPeerStorage();
BtRegistry::registerPeerStorage(_btContext->getInfoHashAsString(),
peerStorage);
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testGetExtensionMessageID();
void testGetExtensionName();
void testGetBencodedData();
void testToString();
void testDoReceivedAction();
void testCreate();
};
CPPUNIT_TEST_SUITE_REGISTRATION(UTPexExtensionMessageTest);
void UTPexExtensionMessageTest::testGetExtensionMessageID()
{
UTPexExtensionMessage msg(1);
CPPUNIT_ASSERT_EQUAL((uint8_t)1, msg.getExtensionMessageID());
}
void UTPexExtensionMessageTest::testGetExtensionName()
{
UTPexExtensionMessage msg(1);
CPPUNIT_ASSERT_EQUAL(string("ut_pex"), msg.getExtensionName());
}
void UTPexExtensionMessageTest::testGetBencodedData()
{
UTPexExtensionMessage msg(1);
PeerHandle p1 = new Peer("192.168.0.1", 6881, 1, 1);
p1->setAllBitfield();
msg.addFreshPeer(p1);// added seeder, check add.f flag
PeerHandle p2 = new Peer("10.1.1.2", 9999, 1, 1);
msg.addFreshPeer(p2);
PeerHandle p3 = new Peer("192.168.0.2", 6882, 1, 1);
msg.addDroppedPeer(p3);
PeerHandle p4 = new Peer("10.1.1.3", 10000, 1, 1);
msg.addDroppedPeer(p4);
char c1[6];
char c2[6];
char c3[6];
char c4[6];
PeerMessageUtil::createcompact(c1, p1->ipaddr, p1->port);
PeerMessageUtil::createcompact(c2, p2->ipaddr, p2->port);
PeerMessageUtil::createcompact(c3, p3->ipaddr, p3->port);
PeerMessageUtil::createcompact(c4, p4->ipaddr, p4->port);
string expected = "d5:added12:"+
string(&c1[0], &c1[6])+string(&c2[0], &c2[6])+
"7:added.f2:207:dropped12:"+
string(&c3[0], &c3[6])+string(&c4[0], &c4[6])+
"e";
string bd = msg.getBencodedData();
CPPUNIT_ASSERT_EQUAL(Util::urlencode(expected),
Util::urlencode(bd));
}
void UTPexExtensionMessageTest::testToString()
{
UTPexExtensionMessage msg(1);
PeerHandle p1 = new Peer("192.168.0.1", 6881, 1, 1);
p1->setAllBitfield();
msg.addFreshPeer(p1);// added seeder, check add.f flag
PeerHandle p2 = new Peer("10.1.1.2", 9999, 1, 1);
msg.addFreshPeer(p2);
PeerHandle p3 = new Peer("192.168.0.2", 6882, 1, 1);
msg.addDroppedPeer(p3);
PeerHandle p4 = new Peer("10.1.1.3", 10000, 1, 1);
msg.addDroppedPeer(p4);
CPPUNIT_ASSERT_EQUAL(string("ut_pex added=2, dropped=2"), msg.toString());
}
void UTPexExtensionMessageTest::testDoReceivedAction()
{
UTPexExtensionMessage msg(1);
PeerHandle p1 = new Peer("192.168.0.1", 6881, 1, 1);
p1->setAllBitfield();
msg.addFreshPeer(p1);// added seeder, check add.f flag
PeerHandle p2 = new Peer("10.1.1.2", 9999, 1, 1);
msg.addFreshPeer(p2);
PeerHandle p3 = new Peer("192.168.0.2", 6882, 1, 1);
msg.addDroppedPeer(p3);
PeerHandle p4 = new Peer("10.1.1.3", 10000, 1, 1);
msg.addDroppedPeer(p4);
msg.setBtContext(_btContext);
msg.doReceivedAction();
CPPUNIT_ASSERT_EQUAL((size_t)2, PEER_STORAGE(_btContext)->getPeers().size());
{
PeerHandle p = PEER_STORAGE(_btContext)->getPeers()[0];
CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), p->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p->port);
}
{
PeerHandle p = PEER_STORAGE(_btContext)->getPeers()[1];
CPPUNIT_ASSERT_EQUAL(string("10.1.1.2"), p->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)9999, p->port);
}
}
void UTPexExtensionMessageTest::testCreate()
{
_btContext->setPieceLength(256*1024);
_btContext->setTotalLength(1024*1024);
char c1[6];
char c2[6];
char c3[6];
char c4[6];
PeerMessageUtil::createcompact(c1, "192.168.0.1", 6881);
PeerMessageUtil::createcompact(c2, "10.1.1.2", 9999);
PeerMessageUtil::createcompact(c3, "192.168.0.2", 6882);
PeerMessageUtil::createcompact(c4, "10.1.1.3",10000);
char id[1] = { 1 };
string data = string(&id[0], &id[1])+"d5:added12:"+
string(&c1[0], &c1[6])+string(&c2[0], &c2[6])+
"7:added.f2:207:dropped12:"+
string(&c3[0], &c3[6])+string(&c4[0], &c4[6])+
"e";
UTPexExtensionMessageHandle msg =
UTPexExtensionMessage::create(_btContext, data.c_str(), data.size());
CPPUNIT_ASSERT_EQUAL((uint8_t)1, msg->getExtensionMessageID());
CPPUNIT_ASSERT_EQUAL((size_t)2, msg->getFreshPeers().size());
CPPUNIT_ASSERT_EQUAL(string("192.168.0.1"), msg->getFreshPeers()[0]->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, msg->getFreshPeers()[0]->port);
CPPUNIT_ASSERT_EQUAL(string("10.1.1.2"), msg->getFreshPeers()[1]->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)9999, msg->getFreshPeers()[1]->port);
CPPUNIT_ASSERT_EQUAL((size_t)2, msg->getDroppedPeers().size());
CPPUNIT_ASSERT_EQUAL(string("192.168.0.2"), msg->getDroppedPeers()[0]->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)6882, msg->getDroppedPeers()[0]->port);
CPPUNIT_ASSERT_EQUAL(string("10.1.1.3"), msg->getDroppedPeers()[1]->ipaddr);
CPPUNIT_ASSERT_EQUAL((uint16_t)10000, msg->getDroppedPeers()[1]->port);
try {
// 0 length data
string in = "";
UTPexExtensionMessage::create(_btContext, in.c_str(), in.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e << endl;
delete e;
}
}

View File

@ -1 +1 @@
d8:announce36:http://aria.rednoah.com/announce.php13:announce-listll16:http://tracker1 el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee
d8:announce36:http://aria.rednoah.com/announce.php13:announce-listll16:http://tracker1 el15:http://tracker2el15:http://tracker3ee7:privatei1e7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee