summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/BtConstants.h4
-rw-r--r--src/BtSetup.cc39
-rw-r--r--src/LpdDispatchMessageCommand.cc88
-rw-r--r--src/LpdDispatchMessageCommand.h69
-rw-r--r--src/LpdMessage.h65
-rw-r--r--src/LpdMessageDispatcher.cc95
-rw-r--r--src/LpdMessageDispatcher.h98
-rw-r--r--src/LpdMessageReceiver.cc107
-rw-r--r--src/LpdMessageReceiver.h74
-rw-r--r--src/LpdReceiveMessageCommand.cc154
-rw-r--r--src/LpdReceiveMessageCommand.h84
-rw-r--r--src/Makefile.am7
-rw-r--r--src/Makefile.in25
-rw-r--r--src/OptionHandlerFactory.cc9
-rw-r--r--src/Peer.cc3
-rw-r--r--src/Peer.h13
-rw-r--r--src/PeerInteractionCommand.cc3
-rw-r--r--src/SocketCore.cc34
-rw-r--r--src/SocketCore.h8
-rw-r--r--src/prefs.cc2
-rw-r--r--src/prefs.h2
-rw-r--r--src/usage_text.h2
-rw-r--r--src/util.cc22
-rw-r--r--src/util.h3
24 files changed, 1003 insertions, 7 deletions
diff --git a/src/BtConstants.h b/src/BtConstants.h
index 8e35309c..d590647e 100644
--- a/src/BtConstants.h
+++ b/src/BtConstants.h
@@ -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_
diff --git a/src/BtSetup.cc b/src/BtSetup.cc
index df59fbcf..756f745c 100644
--- a/src/BtSetup.cc
+++ b/src/BtSetup.cc
@@ -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 =
diff --git a/src/LpdDispatchMessageCommand.cc b/src/LpdDispatchMessageCommand.cc
new file mode 100644
index 00000000..b469935d
--- /dev/null
+++ b/src/LpdDispatchMessageCommand.cc
@@ -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
diff --git a/src/LpdDispatchMessageCommand.h b/src/LpdDispatchMessageCommand.h
new file mode 100644
index 00000000..4e4708e0
--- /dev/null
+++ b/src/LpdDispatchMessageCommand.h
@@ -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_
diff --git a/src/LpdMessage.h b/src/LpdMessage.h
new file mode 100644
index 00000000..c6647e1d
--- /dev/null
+++ b/src/LpdMessage.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_
diff --git a/src/LpdMessageDispatcher.cc b/src/LpdMessageDispatcher.cc
new file mode 100644
index 00000000..3529c524
--- /dev/null
+++ b/src/LpdMessageDispatcher.cc
@@ -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
diff --git a/src/LpdMessageDispatcher.h b/src/LpdMessageDispatcher.h
new file mode 100644
index 00000000..e09c0fa4
--- /dev/null
+++ b/src/LpdMessageDispatcher.h
@@ -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_
diff --git a/src/LpdMessageReceiver.cc b/src/LpdMessageReceiver.cc
new file mode 100644
index 00000000..3d9567f2
--- /dev/null
+++ b/src/LpdMessageReceiver.cc
@@ -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
diff --git a/src/LpdMessageReceiver.h b/src/LpdMessageReceiver.h
new file mode 100644
index 00000000..16d1f895
--- /dev/null
+++ b/src/LpdMessageReceiver.h
@@ -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_
diff --git a/src/LpdReceiveMessageCommand.cc b/src/LpdReceiveMessageCommand.cc
new file mode 100644
index 00000000..ba169b8f
--- /dev/null
+++ b/src/LpdReceiveMessageCommand.cc
@@ -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
diff --git a/src/LpdReceiveMessageCommand.h b/src/LpdReceiveMessageCommand.h
new file mode 100644
index 00000000..251f0cfb
--- /dev/null
+++ b/src/LpdReceiveMessageCommand.h
@@ -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_
diff --git a/src/Makefile.am b/src/Makefile.am
index ee736309..9130fd22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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
diff --git a/src/Makefile.in b/src/Makefile.in
index 44b3dcaf..763cc480 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -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@
diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc
index 520ff42c..764944a1 100644
--- a/src/OptionHandlerFactory.cc
+++ b/src/OptionHandlerFactory.cc
@@ -943,6 +943,15 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
// 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,
TEXT_BT_EXTERNAL_IP,
diff --git a/src/Peer.cc b/src/Peer.cc
index 41ea2ce1..ceef6f9b 100644
--- a/src/Peer.cc
+++ b/src/Peer.cc
@@ -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();
diff --git a/src/Peer.h b/src/Peer.h
index 0291d3db..79158811 100644
--- a/src/Peer.h
+++ b/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;
diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc
index 7df1c75a..9e731324 100644
--- a/src/PeerInteractionCommand.cc
+++ b/src/PeerInteractionCommand.cc
@@ -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);
}
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index d2bc2f10..4be28b30 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -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__
diff --git a/src/SocketCore.h b/src/SocketCore.h
index df69e41d..b4b2714c 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -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.
diff --git a/src/prefs.cc b/src/prefs.cc
index cc612acb..fa451eb2 100644
--- a/src/prefs.cc
+++ b/src/prefs.cc
@@ -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
diff --git a/src/prefs.h b/src/prefs.h
index c8ec63c1..d99124d2 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -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
diff --git a/src/usage_text.h b/src/usage_text.h
index b2dfc1f9..605d8afc 100644
--- a/src/usage_text.h
+++ b/src/usage_text.h
@@ -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.")
diff --git a/src/util.cc b/src/util.cc
index b4ff69d5..fadf445c 100644
--- a/src/util.cc
+++ b/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
diff --git a/src/util.h b/src/util.h
index 7e16a77b..0260a75e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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