mirror of https://github.com/aria2/aria2
2010-02-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added Local Peer Discovery. It is disabled by default. Use --bt-enable-lpd to enable the function. * src/BtConstants.h * src/BtSetup.cc * src/LpdDispatchMessageCommand.cc * src/LpdDispatchMessageCommand.h * src/LpdMessage.h * src/LpdMessageDispatcher.cc * src/LpdMessageDispatcher.h * src/LpdMessageReceiver.cc * src/LpdMessageReceiver.h * src/LpdReceiveMessageCommand.cc * src/LpdReceiveMessageCommand.h * src/Makefile.am * src/OptionHandlerFactory.cc * src/Peer.cc * src/Peer.h * src/PeerInteractionCommand.cc * src/SocketCore.cc * src/SocketCore.h * src/prefs.cc * src/prefs.h * src/usage_text.h * src/util.cc * src/util.h * test/LpdMessageDispatcherTest.cc * test/LpdMessageReceiverTest.cc * test/Makefile.ampull/1/head
parent
aee471e52c
commit
9281f11264
31
ChangeLog
31
ChangeLog
|
@ -1,3 +1,34 @@
|
|||
2010-02-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Added Local Peer Discovery. It is disabled by default. Use
|
||||
--bt-enable-lpd to enable the function.
|
||||
* src/BtConstants.h
|
||||
* src/BtSetup.cc
|
||||
* src/LpdDispatchMessageCommand.cc
|
||||
* src/LpdDispatchMessageCommand.h
|
||||
* src/LpdMessage.h
|
||||
* src/LpdMessageDispatcher.cc
|
||||
* src/LpdMessageDispatcher.h
|
||||
* src/LpdMessageReceiver.cc
|
||||
* src/LpdMessageReceiver.h
|
||||
* src/LpdReceiveMessageCommand.cc
|
||||
* src/LpdReceiveMessageCommand.h
|
||||
* src/Makefile.am
|
||||
* src/OptionHandlerFactory.cc
|
||||
* src/Peer.cc
|
||||
* src/Peer.h
|
||||
* src/PeerInteractionCommand.cc
|
||||
* src/SocketCore.cc
|
||||
* src/SocketCore.h
|
||||
* src/prefs.cc
|
||||
* src/prefs.h
|
||||
* src/usage_text.h
|
||||
* src/util.cc
|
||||
* src/util.h
|
||||
* test/LpdMessageDispatcherTest.cc
|
||||
* test/LpdMessageReceiverTest.cc
|
||||
* test/Makefile.am
|
||||
|
||||
2010-02-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
User-defined custom request headers specified by --header option
|
||||
|
|
|
@ -58,4 +58,8 @@ typedef std::map<std::string, uint8_t> Extensions;
|
|||
|
||||
#define METADATA_PIECE_SIZE (16*1024)
|
||||
|
||||
#define LPD_MULTICAST_ADDR "239.192.152.143"
|
||||
|
||||
#define LPD_MULTICAST_PORT 6771
|
||||
|
||||
#endif // _D_BT_CONSTANTS_
|
||||
|
|
|
@ -60,6 +60,12 @@
|
|||
#include "BtRuntime.h"
|
||||
#include "bittorrent_helper.h"
|
||||
#include "BtStopDownloadCommand.h"
|
||||
#include "LpdReceiveMessageCommand.h"
|
||||
#include "LpdDispatchMessageCommand.h"
|
||||
#include "LpdMessageReceiver.h"
|
||||
#include "LpdMessageDispatcher.h"
|
||||
#include "message.h"
|
||||
#include "SocketCore.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -164,6 +170,39 @@ void BtSetup::setup(std::deque<Command*>& commands,
|
|||
PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e);
|
||||
btRuntime->setListenPort(listenCommand->getPort());
|
||||
}
|
||||
if(option->getAsBool(PREF_BT_ENABLE_LPD) &&
|
||||
(metadataGetMode || torrentAttrs[bittorrent::PRIVATE].i() == 0)) {
|
||||
if(LpdReceiveMessageCommand::getNumInstance() == 0) {
|
||||
SharedHandle<LpdMessageReceiver> receiver
|
||||
(new LpdMessageReceiver(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT));
|
||||
try {
|
||||
receiver->init();
|
||||
receiver->getSocket()->setMulticastTtl(1);
|
||||
} catch(RecoverableException& e) {
|
||||
_logger->info(EX_EXCEPTION_CAUGHT, e);
|
||||
receiver.reset();
|
||||
}
|
||||
if(!receiver.isNull()) {
|
||||
LpdReceiveMessageCommand* cmd =
|
||||
LpdReceiveMessageCommand::getInstance(e, receiver);
|
||||
e->commands.push_back(cmd);
|
||||
}
|
||||
}
|
||||
if(LpdReceiveMessageCommand::getNumInstance()) {
|
||||
const unsigned char* infoHash =
|
||||
bittorrent::getInfoHash(requestGroup->getDownloadContext());
|
||||
SharedHandle<LpdMessageDispatcher> dispatcher
|
||||
(new LpdMessageDispatcher
|
||||
(std::string(&infoHash[0], &infoHash[INFO_HASH_LENGTH]),
|
||||
btRuntime->getListenPort(),
|
||||
LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT,
|
||||
LpdReceiveMessageCommand::getInstance()->getReceiverSocket()));
|
||||
LpdDispatchMessageCommand* cmd =
|
||||
new LpdDispatchMessageCommand(e->newCUID(), dispatcher, e);
|
||||
cmd->setBtRuntime(btRuntime);
|
||||
e->commands.push_back(cmd);
|
||||
}
|
||||
}
|
||||
time_t btStopTimeout = option->getAsInt(PREF_BT_STOP_TIMEOUT);
|
||||
if(btStopTimeout > 0) {
|
||||
BtStopDownloadCommand* stopDownloadCommand =
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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 "LpdDispatchMessageCommand.h"
|
||||
#include "LpdMessageDispatcher.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "Logger.h"
|
||||
#include "RecoverableException.h"
|
||||
#include "SocketCore.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
LpdDispatchMessageCommand::LpdDispatchMessageCommand
|
||||
(int cuid,
|
||||
const SharedHandle<LpdMessageDispatcher>& dispatcher,
|
||||
DownloadEngine* e):
|
||||
Command(cuid),
|
||||
_dispatcher(dispatcher),
|
||||
_e(e),
|
||||
_tryCount(0) {}
|
||||
|
||||
bool LpdDispatchMessageCommand::execute()
|
||||
{
|
||||
if(_btRuntime->isHalt()) {
|
||||
return true;
|
||||
}
|
||||
if(_dispatcher->isAnnounceReady()) {
|
||||
try {
|
||||
logger->info("Dispatching LPD message for infohash=%s",
|
||||
util::toHex(_dispatcher->getInfoHash()).c_str());
|
||||
if(_dispatcher->sendMessage()) {
|
||||
logger->info("Sending LPD message is complete.");
|
||||
_dispatcher->resetAnnounceTimer();
|
||||
_tryCount = 0;
|
||||
} else {
|
||||
++_tryCount;
|
||||
if(_tryCount >= 5) {
|
||||
logger->info("Sending LPD message %u times but all failed.");
|
||||
_dispatcher->resetAnnounceTimer();
|
||||
_tryCount = 0;
|
||||
} else {
|
||||
logger->info("Could not send LPD message, retry shortly.");
|
||||
}
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
logger->info("Failed to send LPD message.", e);
|
||||
_dispatcher->resetAnnounceTimer();
|
||||
_tryCount = 0;
|
||||
}
|
||||
}
|
||||
_e->commands.push_back(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,69 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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_LPD_DISPATCH_MESSAGE_COMMAND_H_
|
||||
#define _D_LPD_DISPATCH_MESSAGE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "SharedHandle.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class LpdMessageDispatcher;
|
||||
class DownloadEngine;
|
||||
class BtRuntime;
|
||||
|
||||
class LpdDispatchMessageCommand:public Command {
|
||||
private:
|
||||
SharedHandle<LpdMessageDispatcher> _dispatcher;
|
||||
DownloadEngine* _e;
|
||||
unsigned int _tryCount;
|
||||
SharedHandle<BtRuntime> _btRuntime;
|
||||
public:
|
||||
LpdDispatchMessageCommand
|
||||
(int cuid,
|
||||
const SharedHandle<LpdMessageDispatcher>& dispatcher,
|
||||
DownloadEngine* e);
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
void setBtRuntime(const SharedHandle<BtRuntime>& btRuntime)
|
||||
{
|
||||
_btRuntime = btRuntime;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _D_LPD_DISPATCH_MESSAGE_COMMAND_H_
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#ifndef _D_LPD_MESSAGE_H_
|
||||
#define _D_LPD_MESSAGE_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Peer.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class LpdMessage {
|
||||
private:
|
||||
SharedHandle<Peer> _peer;
|
||||
std::string _infoHash;
|
||||
public:
|
||||
LpdMessage(const SharedHandle<Peer>& peer, const std::string& infoHash):
|
||||
_peer(peer), _infoHash(infoHash) {}
|
||||
|
||||
const SharedHandle<Peer>& getPeer() const
|
||||
{
|
||||
return _peer;
|
||||
}
|
||||
|
||||
const std::string& getInfoHash() const
|
||||
{
|
||||
return _infoHash;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _D_LPD_MESSAGE_H_
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#include "LpdMessageDispatcher.h"
|
||||
#include "SocketCore.h"
|
||||
#include "A2STR.h"
|
||||
#include "util.h"
|
||||
#include "Logger.h"
|
||||
#include "LogFactory.h"
|
||||
#include "BtConstants.h"
|
||||
#include "RecoverableException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
LpdMessageDispatcher::LpdMessageDispatcher
|
||||
(const std::string& infoHash, uint16_t port,
|
||||
const std::string& multicastAddress, uint16_t multicastPort,
|
||||
const SharedHandle<SocketCore>& socket,
|
||||
time_t interval):
|
||||
_infoHash(infoHash),
|
||||
_port(port),
|
||||
_socket(socket),
|
||||
_multicastAddress(multicastAddress),
|
||||
_multicastPort(multicastPort),
|
||||
_timer(0),
|
||||
_interval(interval),
|
||||
_request(bittorrent::createLpdRequest(_multicastAddress, _multicastPort,
|
||||
_infoHash, _port)),
|
||||
_logger(LogFactory::getInstance()) {}
|
||||
|
||||
bool LpdMessageDispatcher::sendMessage()
|
||||
{
|
||||
return
|
||||
_socket->writeData(_request.c_str(), _request.size(),
|
||||
_multicastAddress, _multicastPort)
|
||||
== (ssize_t)_request.size();
|
||||
}
|
||||
|
||||
bool LpdMessageDispatcher::isAnnounceReady() const
|
||||
{
|
||||
return _timer.elapsed(_interval);
|
||||
}
|
||||
|
||||
void LpdMessageDispatcher::resetAnnounceTimer()
|
||||
{
|
||||
_timer.reset();
|
||||
}
|
||||
|
||||
namespace bittorrent {
|
||||
|
||||
std::string createLpdRequest
|
||||
(const std::string& multicastAddress, uint16_t multicastPort,
|
||||
const std::string& infoHash, uint16_t port)
|
||||
{
|
||||
std::string req = "BT-SEARCH * HTTP/1.1\r\n";
|
||||
strappend(req, "Host: ", multicastAddress, A2STR::COLON_C,
|
||||
util::uitos(multicastPort), A2STR::CRLF);
|
||||
strappend(req, "Port: ", util::uitos(port), A2STR::CRLF);
|
||||
strappend(req, "Infohash: ", util::toHex(infoHash), A2STR::CRLF);
|
||||
req += "\r\n\r\n";
|
||||
return req;
|
||||
}
|
||||
|
||||
} // namespace bittorrent
|
||||
|
||||
} // namespac aria2
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#ifndef _D_LPD_MESSAGE_DISPATCHER_H_
|
||||
#define _D_LPD_MESSAGE_DISPATCHER_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
#include "TimeA2.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class SocketCore;
|
||||
class Logger;
|
||||
|
||||
class LpdMessageDispatcher {
|
||||
private:
|
||||
std::string _infoHash;
|
||||
uint16_t _port;
|
||||
SharedHandle<SocketCore> _socket;
|
||||
std::string _multicastAddress;
|
||||
uint16_t _multicastPort;
|
||||
Time _timer;
|
||||
time_t _interval;
|
||||
std::string _request;
|
||||
Logger* _logger;
|
||||
public:
|
||||
LpdMessageDispatcher
|
||||
(const std::string& infoHash, uint16_t port,
|
||||
const std::string& multicastAddr, uint16_t multicastPort,
|
||||
const SharedHandle<SocketCore>& socket,
|
||||
time_t interval = 5*60);
|
||||
|
||||
// Returns true if _timer reached announce interval, which is by
|
||||
// default 5mins.
|
||||
bool isAnnounceReady() const;
|
||||
|
||||
// Sends LPD message. If message is sent returns true. Otherwise
|
||||
// returns false.
|
||||
bool sendMessage();
|
||||
|
||||
// Reset _timer to the current time.
|
||||
void resetAnnounceTimer();
|
||||
|
||||
const std::string& getInfoHash() const
|
||||
{
|
||||
return _infoHash;
|
||||
}
|
||||
|
||||
uint16_t getPort() const
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
};
|
||||
|
||||
namespace bittorrent {
|
||||
|
||||
std::string createLpdRequest
|
||||
(const std::string& multicastAddress, uint16_t multicastPort,
|
||||
const std::string& infoHash, uint16_t port);
|
||||
|
||||
} // namespace bittorrent
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _D_LPD_MESSAGE_DISPATCHER_H_
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#include "LpdMessageReceiver.h"
|
||||
#include "SocketCore.h"
|
||||
#include "Logger.h"
|
||||
#include "LogFactory.h"
|
||||
#include "HttpHeaderProcessor.h"
|
||||
#include "HttpHeader.h"
|
||||
#include "util.h"
|
||||
#include "LpdMessage.h"
|
||||
#include "RecoverableException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
LpdMessageReceiver::LpdMessageReceiver
|
||||
(const std::string& multicastAddress, uint16_t multicastPort):
|
||||
_multicastAddress(multicastAddress),
|
||||
_multicastPort(multicastPort),
|
||||
_logger(LogFactory::getInstance()) {}
|
||||
|
||||
bool LpdMessageReceiver::init()
|
||||
{
|
||||
try {
|
||||
_socket.reset(new SocketCore(SOCK_DGRAM));
|
||||
// SocketCore::bind(port, flags) cannot be used here, because it
|
||||
// is affected by --interface option.
|
||||
_socket->bindWithFamily(_multicastPort, AF_INET);
|
||||
_socket->joinMulticastGroup(_multicastAddress, _multicastPort);
|
||||
_socket->setNonBlockingMode();
|
||||
_logger->info("Listening multicast group (%s:%u) packet",
|
||||
_multicastAddress.c_str(), _multicastPort);
|
||||
return true;
|
||||
} catch(RecoverableException& e) {
|
||||
_logger->error("Failed to initialize LPD message receiver.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedHandle<LpdMessage> LpdMessageReceiver::receiveMessage()
|
||||
{
|
||||
SharedHandle<LpdMessage> msg;
|
||||
try {
|
||||
unsigned char buf[200];
|
||||
std::pair<std::string, uint16_t> peerAddr;
|
||||
ssize_t length = _socket->readDataFrom(buf, sizeof(buf), peerAddr);
|
||||
if(length == 0) {
|
||||
return msg;
|
||||
}
|
||||
HttpHeaderProcessor proc;
|
||||
proc.update(buf, length);
|
||||
if(!proc.eoh()) {
|
||||
return msg;
|
||||
}
|
||||
SharedHandle<HttpHeader> header = proc.getHttpRequestHeader();
|
||||
std::string infoHashString = header->getFirst("Infohash");
|
||||
uint16_t port = header->getFirstAsUInt("Port");
|
||||
_logger->info("LPD message received infohash=%s, port=%u from %s",
|
||||
infoHashString.c_str(), port, peerAddr.first.c_str());
|
||||
std::string infoHash;
|
||||
if(infoHashString.size() != 40 ||
|
||||
(infoHash = util::fromHex(infoHashString)).empty() ||
|
||||
port == 0) {
|
||||
_logger->info("LPD bad request. infohash=%s", infoHashString.c_str());
|
||||
return msg;
|
||||
}
|
||||
SharedHandle<Peer> peer(new Peer(peerAddr.first, port, false));
|
||||
if(util::inPrivateAddress(peerAddr.first)) {
|
||||
peer->setLocalPeer(true);
|
||||
}
|
||||
msg.reset(new LpdMessage(peer, infoHash));
|
||||
} catch(RecoverableException& e) {
|
||||
_logger->info("Failed to receive LPD message.", e);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*/
|
||||
#ifndef _LPD_MESSAGE_RECEIVER_H_
|
||||
#define _LPD_MESSAGE_RECEIVER_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class SocketCore;
|
||||
class Logger;
|
||||
class LpdMessage;
|
||||
|
||||
class LpdMessageReceiver {
|
||||
private:
|
||||
SharedHandle<SocketCore> _socket;
|
||||
std::string _multicastAddress;
|
||||
uint16_t _multicastPort;
|
||||
Logger* _logger;
|
||||
public:
|
||||
// Currently only IPv4 multicastAddresses are supported.
|
||||
LpdMessageReceiver
|
||||
(const std::string& multicastAddress, uint16_t multicastPort);
|
||||
|
||||
// No throw.
|
||||
bool init();
|
||||
|
||||
// Receives LPD message and process it. Returns false if message is
|
||||
// not available.
|
||||
SharedHandle<LpdMessage> receiveMessage();
|
||||
|
||||
SharedHandle<SocketCore> getSocket() const
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _LPD_MESSAGE_RECEIVER_H_
|
|
@ -0,0 +1,154 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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 "LpdReceiveMessageCommand.h"
|
||||
#include "DownloadEngine.h"
|
||||
#include "SocketCore.h"
|
||||
#include "LpdMessageReceiver.h"
|
||||
#include "RequestGroupMan.h"
|
||||
#include "DownloadContext.h"
|
||||
#include "PeerStorage.h"
|
||||
#include "Peer.h"
|
||||
#include "RequestGroup.h"
|
||||
#include "BtRegistry.h"
|
||||
#include "Logger.h"
|
||||
#include "PieceStorage.h"
|
||||
#include "BtRuntime.h"
|
||||
#include "BtProgressInfoFile.h"
|
||||
#include "BtAnnounce.h"
|
||||
#include "LpdMessage.h"
|
||||
#include "bittorrent_helper.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
unsigned int LpdReceiveMessageCommand::__numInstance = 0;
|
||||
|
||||
LpdReceiveMessageCommand* LpdReceiveMessageCommand::__instance = 0;
|
||||
|
||||
LpdReceiveMessageCommand::LpdReceiveMessageCommand
|
||||
(int32_t cuid, const SharedHandle<LpdMessageReceiver>& receiver,
|
||||
DownloadEngine* e):Command(cuid), _receiver(receiver), _e(e)
|
||||
{
|
||||
_e->addSocketForReadCheck(_receiver->getSocket(), this);
|
||||
++__numInstance;
|
||||
}
|
||||
|
||||
LpdReceiveMessageCommand::~LpdReceiveMessageCommand()
|
||||
{
|
||||
_e->deleteSocketForReadCheck(_receiver->getSocket(), this);
|
||||
--__numInstance;
|
||||
if(__numInstance == 0) {
|
||||
__instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool LpdReceiveMessageCommand::execute()
|
||||
{
|
||||
if(_e->_requestGroupMan->downloadFinished() || _e->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
for(size_t i = 0; i < 20; ++i) {
|
||||
SharedHandle<LpdMessage> m = _receiver->receiveMessage();
|
||||
if(m.isNull()) {
|
||||
break;
|
||||
}
|
||||
SharedHandle<BtRegistry> reg = _e->getBtRegistry();
|
||||
SharedHandle<DownloadContext> dctx =
|
||||
reg->getDownloadContext(m->getInfoHash());
|
||||
if(dctx.isNull()) {
|
||||
if(logger->debug()) {
|
||||
logger->debug("Download Context is null for infohash=%s.",
|
||||
util::toHex(m->getInfoHash()).c_str());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const BDE& torrentAttrs = dctx->getAttribute(bittorrent::BITTORRENT);
|
||||
if(torrentAttrs.containsKey(bittorrent::PRIVATE)) {
|
||||
if(torrentAttrs[bittorrent::PRIVATE].i() == 1) {
|
||||
if(logger->debug()) {
|
||||
logger->debug("Ignore LPD message because the torrent is private.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
RequestGroup* group = dctx->getOwnerRequestGroup();
|
||||
assert(group);
|
||||
BtObject btobj = reg->get(group->getGID());
|
||||
assert(!btobj.isNull());
|
||||
SharedHandle<PeerStorage> peerStorage = btobj._peerStorage;
|
||||
assert(!peerStorage.isNull());
|
||||
SharedHandle<Peer> peer = m->getPeer();
|
||||
if(peerStorage->addPeer(peer)) {
|
||||
if(logger->debug()) {
|
||||
logger->debug("LPD peer %s:%u local=%d added.",
|
||||
peer->ipaddr.c_str(), peer->port,
|
||||
peer->isLocalPeer()?1:0);
|
||||
}
|
||||
} else {
|
||||
if(logger->debug()) {
|
||||
logger->debug("LPD peer %s:%u local=%d not added.",
|
||||
peer->ipaddr.c_str(), peer->port,
|
||||
peer->isLocalPeer()?1:0);
|
||||
}
|
||||
}
|
||||
}
|
||||
_e->commands.push_back(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedHandle<SocketCore> LpdReceiveMessageCommand::getReceiverSocket() const
|
||||
{
|
||||
return _receiver->getSocket();
|
||||
}
|
||||
|
||||
LpdReceiveMessageCommand*
|
||||
LpdReceiveMessageCommand::getInstance
|
||||
(DownloadEngine* e, const SharedHandle<LpdMessageReceiver>& receiver)
|
||||
{
|
||||
if(__numInstance == 0) {
|
||||
__instance = new LpdReceiveMessageCommand(e->newCUID(), receiver, e);
|
||||
}
|
||||
return __instance;
|
||||
}
|
||||
|
||||
LpdReceiveMessageCommand* LpdReceiveMessageCommand::getInstance()
|
||||
{
|
||||
if(__numInstance == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return __instance;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,84 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2010 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_LPD_RECEIVE_MESSAGE_COMMAND_H_
|
||||
#define _D_LPD_RECEIVE_MESSAGE_COMMAND_H_
|
||||
|
||||
#include "Command.h"
|
||||
#include "SharedHandle.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class LpdMessageReceiver;
|
||||
class DownloadEngine;
|
||||
class SocketCore;
|
||||
|
||||
class LpdReceiveMessageCommand:public Command {
|
||||
private:
|
||||
SharedHandle<LpdMessageReceiver> _receiver;
|
||||
|
||||
static unsigned int __numInstance;
|
||||
|
||||
static LpdReceiveMessageCommand* __instance;
|
||||
|
||||
LpdReceiveMessageCommand
|
||||
(int32_t cuid, const SharedHandle<LpdMessageReceiver>& receiver,
|
||||
DownloadEngine* e);
|
||||
protected:
|
||||
DownloadEngine* _e;
|
||||
|
||||
public:
|
||||
virtual ~LpdReceiveMessageCommand();
|
||||
|
||||
virtual bool execute();
|
||||
|
||||
SharedHandle<SocketCore> getReceiverSocket() const;
|
||||
|
||||
static LpdReceiveMessageCommand*
|
||||
getInstance
|
||||
(DownloadEngine* e, const SharedHandle<LpdMessageReceiver>& receiver);
|
||||
|
||||
// If __numInstance is 0, then return 0. If __numInstance > 0, it
|
||||
// returns __instance
|
||||
static LpdReceiveMessageCommand* getInstance();
|
||||
|
||||
static unsigned int getNumInstance()
|
||||
{
|
||||
return __numInstance;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // _D_LPD_RECEIVE_MESSAGE_COMMAND_H_
|
|
@ -440,7 +440,12 @@ SRCS += PeerAbstractCommand.cc PeerAbstractCommand.h\
|
|||
bencode.cc bencode.h\
|
||||
bittorrent_helper.cc bittorrent_helper.h\
|
||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h\
|
||||
PriorityPieceSelector.cc PriorityPieceSelector.h
|
||||
PriorityPieceSelector.cc PriorityPieceSelector.h\
|
||||
LpdMessageDispatcher.cc LpdMessageDispatcher.h\
|
||||
LpdMessageReceiver.cc LpdMessageReceiver.h\
|
||||
LpdMessage.h\
|
||||
LpdReceiveMessageCommand.cc LpdReceiveMessageCommand.h\
|
||||
LpdDispatchMessageCommand.cc LpdDispatchMessageCommand.h
|
||||
endif # ENABLE_BITTORRENT
|
||||
|
||||
if ENABLE_METALINK
|
||||
|
|
|
@ -243,7 +243,12 @@ bin_PROGRAMS = aria2c$(EXEEXT)
|
|||
@ENABLE_BITTORRENT_TRUE@ bencode.cc bencode.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.cc bittorrent_helper.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.cc BtStopDownloadCommand.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.cc PriorityPieceSelector.h
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.cc PriorityPieceSelector.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageDispatcher.cc LpdMessageDispatcher.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageReceiver.cc LpdMessageReceiver.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessage.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdReceiveMessageCommand.cc LpdReceiveMessageCommand.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdDispatchMessageCommand.cc LpdDispatchMessageCommand.h
|
||||
|
||||
@ENABLE_METALINK_TRUE@am__append_14 = Metalinker.cc Metalinker.h\
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
|
||||
|
@ -570,8 +575,12 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
|
|||
IndexBtMessageValidator.h ExtensionMessageRegistry.h \
|
||||
bencode.cc bencode.h bittorrent_helper.cc bittorrent_helper.h \
|
||||
BtStopDownloadCommand.cc BtStopDownloadCommand.h \
|
||||
PriorityPieceSelector.cc PriorityPieceSelector.h Metalinker.cc \
|
||||
Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
|
||||
PriorityPieceSelector.cc PriorityPieceSelector.h \
|
||||
LpdMessageDispatcher.cc LpdMessageDispatcher.h \
|
||||
LpdMessageReceiver.cc LpdMessageReceiver.h LpdMessage.h \
|
||||
LpdReceiveMessageCommand.cc LpdReceiveMessageCommand.h \
|
||||
LpdDispatchMessageCommand.cc LpdDispatchMessageCommand.h \
|
||||
Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
|
||||
MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
|
||||
MetalinkParserController.cc MetalinkParserController.h \
|
||||
MetalinkParserStateMachine.cc MetalinkParserStateMachine.h \
|
||||
|
@ -734,7 +743,11 @@ am__objects_6 =
|
|||
@ENABLE_BITTORRENT_TRUE@ bencode.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ bittorrent_helper.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ BtStopDownloadCommand.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.$(OBJEXT)
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelector.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageDispatcher.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageReceiver.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdReceiveMessageCommand.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdDispatchMessageCommand.$(OBJEXT)
|
||||
@ENABLE_METALINK_TRUE@am__objects_14 = Metalinker.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
|
||||
|
@ -1465,6 +1478,10 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Logger.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LongestSequencePieceSelector.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdDispatchMessageCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdMessageDispatcher.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdMessageReceiver.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdReceiveMessageCommand.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshake.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryBufferPreDownloadHandler.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
|
||||
|
|
|
@ -942,6 +942,15 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
|
|||
#endif // ENABLE_BITTORRENT || ENABLE_METALINK
|
||||
// BitTorrent Specific Options
|
||||
#ifdef ENABLE_BITTORRENT
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new BooleanOptionHandler
|
||||
(PREF_BT_ENABLE_LPD,
|
||||
TEXT_BT_ENABLE_LPD,
|
||||
V_FALSE,
|
||||
OptionHandler::OPT_ARG));
|
||||
op->addTag(TAG_BITTORRENT);
|
||||
handlers.push_back(op);
|
||||
}
|
||||
{
|
||||
SharedHandle<OptionHandler> op(new DefaultOptionHandler
|
||||
(PREF_BT_EXTERNAL_IP,
|
||||
|
|
|
@ -55,7 +55,8 @@ Peer::Peer(std::string ipaddr, uint16_t port, bool incoming):
|
|||
_badConditionStartTime(0),
|
||||
_seeder(false),
|
||||
_res(0),
|
||||
_incoming(incoming)
|
||||
_incoming(incoming),
|
||||
_localPeer(false)
|
||||
{
|
||||
memset(_peerId, 0, PEER_ID_LENGTH);
|
||||
resetStatus();
|
||||
|
|
13
src/Peer.h
13
src/Peer.h
|
@ -78,6 +78,9 @@ private:
|
|||
// If true, port is assumed not to be a listening port.
|
||||
bool _incoming;
|
||||
|
||||
// If true, this peer is from local network.
|
||||
bool _localPeer;
|
||||
|
||||
// Before calling updateSeeder(), make sure that
|
||||
// allocateSessionResource() is called and _res is created.
|
||||
// Otherwise assertion fails.
|
||||
|
@ -282,6 +285,16 @@ public:
|
|||
|
||||
void setIncomingPeer(bool incoming);
|
||||
|
||||
bool isLocalPeer() const
|
||||
{
|
||||
return _localPeer;
|
||||
}
|
||||
|
||||
void setLocalPeer(bool flag)
|
||||
{
|
||||
_localPeer = flag;
|
||||
}
|
||||
|
||||
void setBtMessageDispatcher(const WeakHandle<BtMessageDispatcher>& dpt);
|
||||
|
||||
size_t countOutstandingUpload() const;
|
||||
|
|
|
@ -189,7 +189,8 @@ PeerInteractionCommand::PeerInteractionCommand
|
|||
(getOption()->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL));
|
||||
btInteractive->setRequestGroupMan(e->_requestGroupMan);
|
||||
btInteractive->setBtMessageFactory(factory);
|
||||
if(metadataGetMode || torrentAttrs[bittorrent::PRIVATE].i() == 0) {
|
||||
if((metadataGetMode || torrentAttrs[bittorrent::PRIVATE].i() == 0) &&
|
||||
!peer->isLocalPeer()) {
|
||||
if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) {
|
||||
btInteractive->setUTPexEnabled(true);
|
||||
}
|
||||
|
|
|
@ -253,6 +253,18 @@ static sock_t bindTo
|
|||
return -1;
|
||||
}
|
||||
|
||||
void SocketCore::bindWithFamily(uint16_t port, int family, int flags)
|
||||
{
|
||||
closeConnection();
|
||||
std::string error;
|
||||
sock_t fd = bindTo(0, port, family, _sockType, flags, error);
|
||||
if(fd == (sock_t) -1) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_SOCKET_BIND, error.c_str()).str());
|
||||
} else {
|
||||
sockfd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketCore::bind(uint16_t port, int flags)
|
||||
{
|
||||
closeConnection();
|
||||
|
@ -403,6 +415,28 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port)
|
|||
}
|
||||
}
|
||||
|
||||
void SocketCore::setSockOpt
|
||||
(int level, int optname, void* optval, socklen_t optlen)
|
||||
{
|
||||
if(setsockopt(sockfd, level, optname, optval, optlen) < 0) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_SOCKET_SET_OPT, errorMsg()).str());
|
||||
}
|
||||
}
|
||||
|
||||
void SocketCore::setMulticastTtl(unsigned char ttl)
|
||||
{
|
||||
setSockOpt(IPPROTO_IP, IP_MULTICAST_TTL, (a2_sockopt_t)&ttl, sizeof(ttl));
|
||||
}
|
||||
|
||||
void SocketCore::joinMulticastGroup(const std::string& ipaddr, uint16_t port)
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(ipaddr.c_str());
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
setSockOpt(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
}
|
||||
|
||||
void SocketCore::setNonBlockingMode()
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
|
|
|
@ -135,6 +135,8 @@ private:
|
|||
|
||||
#endif // HAVE_EPOLL
|
||||
|
||||
void setSockOpt(int level, int optname, void* optval, socklen_t optlen);
|
||||
|
||||
SocketCore(sock_t sockfd, int sockType);
|
||||
public:
|
||||
SocketCore(int sockType = SOCK_STREAM);
|
||||
|
@ -144,6 +146,12 @@ public:
|
|||
|
||||
bool isOpen() const { return sockfd != (sock_t) -1; }
|
||||
|
||||
void setMulticastTtl(unsigned char ttl);
|
||||
|
||||
void joinMulticastGroup(const std::string& ipaddr, uint16_t port);
|
||||
|
||||
void bindWithFamily(uint16_t port, int family, int flags = AI_PASSIVE);
|
||||
|
||||
/**
|
||||
* Creates a socket and bind it with locahost's address and port.
|
||||
* flags is set to struct addrinfo's ai_flags.
|
||||
|
|
|
@ -316,6 +316,8 @@ const std::string PREF_BT_PRIORITIZE_PIECE("bt-prioritize-piece");
|
|||
const std::string PREF_BT_SAVE_METADATA("bt-save-metadata");
|
||||
// values: true | false
|
||||
const std::string PREF_BT_METADATA_ONLY("bt-metadata-only");
|
||||
// values: true | false
|
||||
const std::string PREF_BT_ENABLE_LPD("bt-enable-lpd");
|
||||
|
||||
/**
|
||||
* Metalink related preferences
|
||||
|
|
|
@ -320,6 +320,8 @@ extern const std::string PREF_BT_PRIORITIZE_PIECE;
|
|||
extern const std::string PREF_BT_SAVE_METADATA;
|
||||
// values: true | false
|
||||
extern const std::string PREF_BT_METADATA_ONLY;
|
||||
// values: true | false
|
||||
extern const std::string PREF_BT_ENABLE_LPD;
|
||||
|
||||
/**
|
||||
* Metalink related preferences
|
||||
|
|
|
@ -608,3 +608,5 @@
|
|||
#define TEXT_HUMAN_READABLE \
|
||||
_(" --human-readable[=true|false] Print sizes and speed in human readable format\n" \
|
||||
" (e.g., 1.2Ki, 3.4Mi) in the console readout.")
|
||||
#define TEXT_BT_ENABLE_LPD \
|
||||
_(" --bt-enable-lpd[=true|false] Enable Local Peer Discovery.")
|
||||
|
|
22
src/util.cc
22
src/util.cc
|
@ -1172,6 +1172,28 @@ void generateRandomKey(unsigned char* key)
|
|||
#endif // !ENABLE_MESSAGE_DIGEST
|
||||
}
|
||||
|
||||
// Returns true is given numeric ipv4addr is in Private Address Space.
|
||||
//
|
||||
// From Section.3 RFC1918
|
||||
// 10.0.0.0 - 10.255.255.255 (10/8 prefix)
|
||||
// 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
|
||||
// 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
|
||||
bool inPrivateAddress(const std::string& ipv4addr)
|
||||
{
|
||||
if(util::startsWith(ipv4addr, "10.") ||
|
||||
util::startsWith(ipv4addr, "192.168.")) {
|
||||
return true;
|
||||
}
|
||||
if(util::startsWith(ipv4addr, "172.")) {
|
||||
for(int i = 16; i <= 31; ++i) {
|
||||
if(util::startsWith(ipv4addr, "172."+util::itos(i)+".")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -378,6 +378,9 @@ std::string fixTaintedBasename(const std::string& src);
|
|||
// by key. Caller must allocate at least 20 bytes for generated key.
|
||||
void generateRandomKey(unsigned char* key);
|
||||
|
||||
// Returns true is given numeric ipv4addr is in Private Address Space.
|
||||
bool inPrivateAddress(const std::string& ipv4addr);
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#include "LpdMessageDispatcher.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "Exception.h"
|
||||
#include "util.h"
|
||||
#include "LpdMessageDispatcher.h"
|
||||
#include "SocketCore.h"
|
||||
#include "BtConstants.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class LpdMessageDispatcherTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(LpdMessageDispatcherTest);
|
||||
CPPUNIT_TEST(testCreateLpdRequest);
|
||||
CPPUNIT_TEST(testSendMessage);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void testCreateLpdRequest();
|
||||
void testSendMessage();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(LpdMessageDispatcherTest);
|
||||
|
||||
void LpdMessageDispatcherTest::testCreateLpdRequest()
|
||||
{
|
||||
std::string infoHashString = "cd41c7fdddfd034a15a04d7ff881216e01c4ceaf";
|
||||
CPPUNIT_ASSERT_EQUAL
|
||||
(std::string("BT-SEARCH * HTTP/1.1\r\n"
|
||||
"Host: 239.192.152.143:6771\r\n"
|
||||
"Port: 6000\r\n"
|
||||
"Infohash: cd41c7fdddfd034a15a04d7ff881216e01c4ceaf\r\n"
|
||||
"\r\n\r\n"),
|
||||
bittorrent::createLpdRequest("239.192.152.143", 6771,
|
||||
util::fromHex(infoHashString), 6000));
|
||||
}
|
||||
|
||||
void LpdMessageDispatcherTest::testSendMessage()
|
||||
{
|
||||
SharedHandle<SocketCore> recvsock(new SocketCore(SOCK_DGRAM));
|
||||
recvsock->bind(LPD_MULTICAST_PORT);
|
||||
recvsock->joinMulticastGroup(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
recvsock->setMulticastTtl(0);
|
||||
LpdMessageDispatcher d("cd41c7fdddfd034a15a04d7ff881216e01c4ceaf", 6000,
|
||||
LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT,
|
||||
recvsock);
|
||||
|
||||
CPPUNIT_ASSERT(d.sendMessage());
|
||||
|
||||
unsigned char buf[200];
|
||||
|
||||
std::pair<std::string, uint16_t> peer;
|
||||
ssize_t nbytes = recvsock->readDataFrom(buf, sizeof(buf), peer);
|
||||
buf[nbytes] = '\0';
|
||||
std::stringstream temp;
|
||||
temp << "BT-SEARCH * HTTP/1.1\r\n"
|
||||
<< "Host: " << LPD_MULTICAST_ADDR << ":" << LPD_MULTICAST_PORT << "\r\n"
|
||||
<< "Port: " << d.getPort() << "\r\n"
|
||||
<< "Infohash: " << util::toHex(d.getInfoHash()) << "\r\n"
|
||||
<< "\r\n\r\n";
|
||||
CPPUNIT_ASSERT_EQUAL(temp.str(), std::string(&buf[0], &buf[nbytes]));
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,75 @@
|
|||
#include "LpdMessageReceiver.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "Exception.h"
|
||||
#include "util.h"
|
||||
#include "LpdMessageReceiver.h"
|
||||
#include "SocketCore.h"
|
||||
#include "BtConstants.h"
|
||||
#include "LpdMessage.h"
|
||||
#include "LpdMessageDispatcher.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class LpdMessageReceiverTest:public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(LpdMessageReceiverTest);
|
||||
CPPUNIT_TEST(testReceiveMessage);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
public:
|
||||
void testReceiveMessage();
|
||||
};
|
||||
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(LpdMessageReceiverTest);
|
||||
|
||||
void LpdMessageReceiverTest::testReceiveMessage()
|
||||
{
|
||||
LpdMessageReceiver rcv(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
CPPUNIT_ASSERT(rcv.init());
|
||||
|
||||
SharedHandle<SocketCore> sendsock = rcv.getSocket();
|
||||
sendsock->setMulticastTtl(0);
|
||||
|
||||
std::string infoHashString = "cd41c7fdddfd034a15a04d7ff881216e01c4ceaf";
|
||||
std::string infoHash = util::fromHex(infoHashString);
|
||||
std::string request =
|
||||
bittorrent::createLpdRequest(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT,
|
||||
infoHash,
|
||||
6000);
|
||||
|
||||
sendsock->writeData(request.c_str(), request.size(),
|
||||
LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
|
||||
SharedHandle<LpdMessage> msg = rcv.receiveMessage();
|
||||
CPPUNIT_ASSERT(!msg.isNull());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("cd41c7fdddfd034a15a04d7ff881216e01c4ceaf"),
|
||||
util::toHex(msg->getInfoHash()));
|
||||
CPPUNIT_ASSERT_EQUAL((uint16_t)6000, msg->getPeer()->port);
|
||||
|
||||
// Bad infohash
|
||||
std::string badInfoHashString = "cd41c7fdddfd034a15a04d7ff881216e01c4ce";
|
||||
request =
|
||||
bittorrent::createLpdRequest(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT,
|
||||
util::fromHex(badInfoHashString),
|
||||
6000);
|
||||
sendsock->writeData(request.c_str(), request.size(),
|
||||
LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
|
||||
CPPUNIT_ASSERT(rcv.receiveMessage().isNull());
|
||||
|
||||
// Bad port
|
||||
request =
|
||||
bittorrent::createLpdRequest(LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT,
|
||||
infoHash,
|
||||
0);
|
||||
sendsock->writeData(request.c_str(), request.size(),
|
||||
LPD_MULTICAST_ADDR, LPD_MULTICAST_PORT);
|
||||
|
||||
CPPUNIT_ASSERT(rcv.receiveMessage().isNull());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -191,7 +191,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
|
|||
BittorrentHelperTest.cc\
|
||||
PriorityPieceSelectorTest.cc\
|
||||
MockPieceSelector.h\
|
||||
extension_message_test_helper.h
|
||||
extension_message_test_helper.h\
|
||||
LpdMessageDispatcherTest.cc\
|
||||
LpdMessageReceiverTest.cc
|
||||
endif # ENABLE_BITTORRENT
|
||||
|
||||
if ENABLE_METALINK
|
||||
|
|
|
@ -141,7 +141,9 @@ check_PROGRAMS = $(am__EXEEXT_1)
|
|||
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelectorTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ MockPieceSelector.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ extension_message_test_helper.h
|
||||
@ENABLE_BITTORRENT_TRUE@ extension_message_test_helper.h\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageDispatcherTest.cc\
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageReceiverTest.cc
|
||||
|
||||
@ENABLE_METALINK_TRUE@am__append_7 = MetalinkerTest.cc\
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
|
||||
|
@ -266,7 +268,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
|||
MockExtensionMessage.h MockExtensionMessageFactory.h \
|
||||
MockPieceStorage.h BencodeTest.cc BittorrentHelperTest.cc \
|
||||
PriorityPieceSelectorTest.cc MockPieceSelector.h \
|
||||
extension_message_test_helper.h MetalinkerTest.cc \
|
||||
extension_message_test_helper.h LpdMessageDispatcherTest.cc \
|
||||
LpdMessageReceiverTest.cc MetalinkerTest.cc \
|
||||
MetalinkEntryTest.cc Metalink2RequestGroupTest.cc \
|
||||
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
|
||||
MetalinkParserControllerTest.cc MetalinkProcessorTest.cc
|
||||
|
@ -356,7 +359,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \
|
|||
@ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ BencodeTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ BittorrentHelperTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelectorTest.$(OBJEXT)
|
||||
@ENABLE_BITTORRENT_TRUE@ PriorityPieceSelectorTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageDispatcherTest.$(OBJEXT) \
|
||||
@ENABLE_BITTORRENT_TRUE@ LpdMessageReceiverTest.$(OBJEXT)
|
||||
@ENABLE_METALINK_TRUE@am__objects_7 = MetalinkerTest.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
|
||||
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
|
||||
|
@ -824,6 +829,8 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidatorTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidatorTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LongestSequencePieceSelectorTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdMessageDispatcherTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LpdMessageReceiverTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshakeTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MagnetTest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelperTest.Po@am__quote@
|
||||
|
|
Loading…
Reference in New Issue