PeerInteractionCommand.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "PeerInteractionCommand.h"
  36. #include <algorithm>
  37. #include "DownloadEngine.h"
  38. #include "PeerInitiateConnectionCommand.h"
  39. #include "DefaultBtInteractive.h"
  40. #include "DlAbortEx.h"
  41. #include "message.h"
  42. #include "prefs.h"
  43. #include "Socket.h"
  44. #include "Option.h"
  45. #include "DownloadContext.h"
  46. #include "Peer.h"
  47. #include "BtMessage.h"
  48. #include "BtRuntime.h"
  49. #include "PeerStorage.h"
  50. #include "DefaultBtMessageDispatcher.h"
  51. #include "DefaultBtMessageReceiver.h"
  52. #include "DefaultBtRequestFactory.h"
  53. #include "DefaultBtMessageFactory.h"
  54. #include "DefaultBtInteractive.h"
  55. #include "PeerConnection.h"
  56. #include "ExtensionMessageFactory.h"
  57. #include "DHTRoutingTable.h"
  58. #include "DHTTaskQueue.h"
  59. #include "DHTTaskFactory.h"
  60. #include "DHTNode.h"
  61. #include "DHTSetup.h"
  62. #include "DHTRegistry.h"
  63. #include "PieceStorage.h"
  64. #include "RequestGroup.h"
  65. #include "BtAnnounce.h"
  66. #include "BtProgressInfoFile.h"
  67. #include "DefaultExtensionMessageFactory.h"
  68. #include "RequestGroupMan.h"
  69. #include "ExtensionMessageRegistry.h"
  70. #include "bittorrent_helper.h"
  71. #include "UTMetadataRequestFactory.h"
  72. #include "UTMetadataRequestTracker.h"
  73. #include "ServerStatMan.h"
  74. #include "FileAllocationEntry.h"
  75. #include "CheckIntegrityEntry.h"
  76. namespace aria2 {
  77. PeerInteractionCommand::PeerInteractionCommand
  78. (cuid_t cuid,
  79. RequestGroup* requestGroup,
  80. const SharedHandle<Peer>& p,
  81. DownloadEngine* e,
  82. const SharedHandle<BtRuntime>& btRuntime,
  83. const SharedHandle<PieceStorage>& pieceStorage,
  84. const SharedHandle<PeerStorage>& peerStorage,
  85. const SocketHandle& s,
  86. Seq sequence,
  87. const PeerConnectionHandle& passedPeerConnection)
  88. :PeerAbstractCommand(cuid, p, e, s),
  89. requestGroup_(requestGroup),
  90. btRuntime_(btRuntime),
  91. pieceStorage_(pieceStorage),
  92. peerStorage_(peerStorage),
  93. sequence_(sequence)
  94. {
  95. // TODO move following bunch of processing to separate method, like init()
  96. if(sequence_ == INITIATOR_SEND_HANDSHAKE) {
  97. disableReadCheckSocket();
  98. setWriteCheckSocket(getSocket());
  99. setTimeout(getOption()->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
  100. }
  101. SharedHandle<TorrentAttribute> torrentAttrs =
  102. bittorrent::getTorrentAttrs(requestGroup_->getDownloadContext());
  103. bool metadataGetMode = torrentAttrs->metadata.empty();
  104. SharedHandle<ExtensionMessageRegistry> exMsgRegistry
  105. (new ExtensionMessageRegistry());
  106. SharedHandle<UTMetadataRequestFactory> utMetadataRequestFactory;
  107. SharedHandle<UTMetadataRequestTracker> utMetadataRequestTracker;
  108. if(metadataGetMode) {
  109. utMetadataRequestFactory.reset(new UTMetadataRequestFactory());
  110. utMetadataRequestTracker.reset(new UTMetadataRequestTracker());
  111. }
  112. SharedHandle<DefaultExtensionMessageFactory> extensionMessageFactory
  113. (new DefaultExtensionMessageFactory(getPeer(), exMsgRegistry));
  114. extensionMessageFactory->setPeerStorage(peerStorage);
  115. extensionMessageFactory->setDownloadContext
  116. (requestGroup_->getDownloadContext());
  117. extensionMessageFactory->setUTMetadataRequestTracker
  118. (utMetadataRequestTracker);
  119. // PieceStorage will be set later.
  120. SharedHandle<DefaultBtMessageFactory> factory(new DefaultBtMessageFactory());
  121. factory->setCuid(cuid);
  122. factory->setDownloadContext(requestGroup_->getDownloadContext());
  123. factory->setPieceStorage(pieceStorage);
  124. factory->setPeerStorage(peerStorage);
  125. factory->setExtensionMessageFactory(extensionMessageFactory);
  126. factory->setPeer(getPeer());
  127. factory->setLocalNode(DHTRegistry::getData().localNode);
  128. factory->setRoutingTable(DHTRegistry::getData().routingTable);
  129. factory->setTaskQueue(DHTRegistry::getData().taskQueue);
  130. factory->setTaskFactory(DHTRegistry::getData().taskFactory);
  131. if(metadataGetMode) {
  132. factory->enableMetadataGetMode();
  133. }
  134. PeerConnectionHandle peerConnection;
  135. if(passedPeerConnection.isNull()) {
  136. peerConnection.reset(new PeerConnection(cuid, getSocket()));
  137. } else {
  138. peerConnection = passedPeerConnection;
  139. }
  140. SharedHandle<DefaultBtMessageDispatcher> dispatcher
  141. (new DefaultBtMessageDispatcher());
  142. dispatcher->setCuid(cuid);
  143. dispatcher->setPeer(getPeer());
  144. dispatcher->setDownloadContext(requestGroup_->getDownloadContext());
  145. dispatcher->setPieceStorage(pieceStorage);
  146. dispatcher->setPeerStorage(peerStorage);
  147. dispatcher->setRequestTimeout(getOption()->getAsInt(PREF_BT_REQUEST_TIMEOUT));
  148. dispatcher->setBtMessageFactory(factory);
  149. dispatcher->setRequestGroupMan(getDownloadEngine()->getRequestGroupMan());
  150. DefaultBtMessageReceiverHandle receiver(new DefaultBtMessageReceiver());
  151. receiver->setDownloadContext(requestGroup_->getDownloadContext());
  152. receiver->setPeerConnection(peerConnection);
  153. receiver->setDispatcher(dispatcher);
  154. receiver->setBtMessageFactory(factory);
  155. SharedHandle<DefaultBtRequestFactory> reqFactory
  156. (new DefaultBtRequestFactory());
  157. reqFactory->setPeer(getPeer());
  158. reqFactory->setPieceStorage(pieceStorage);
  159. reqFactory->setBtMessageDispatcher(dispatcher);
  160. reqFactory->setBtMessageFactory(factory);
  161. DefaultBtInteractiveHandle btInteractive
  162. (new DefaultBtInteractive(requestGroup_->getDownloadContext(), getPeer()));
  163. btInteractive->setBtRuntime(btRuntime_);
  164. btInteractive->setPieceStorage(pieceStorage_);
  165. btInteractive->setPeerStorage(peerStorage); // Note: Not a member variable.
  166. btInteractive->setCuid(cuid);
  167. btInteractive->setBtMessageReceiver(receiver);
  168. btInteractive->setDispatcher(dispatcher);
  169. btInteractive->setBtRequestFactory(reqFactory);
  170. btInteractive->setPeerConnection(peerConnection);
  171. btInteractive->setExtensionMessageFactory(extensionMessageFactory);
  172. btInteractive->setExtensionMessageRegistry(exMsgRegistry);
  173. btInteractive->setKeepAliveInterval
  174. (getOption()->getAsInt(PREF_BT_KEEP_ALIVE_INTERVAL));
  175. btInteractive->setRequestGroupMan(getDownloadEngine()->getRequestGroupMan());
  176. btInteractive->setBtMessageFactory(factory);
  177. if((metadataGetMode || !torrentAttrs->privateTorrent) &&
  178. !getPeer()->isLocalPeer()) {
  179. if(getOption()->getAsBool(PREF_ENABLE_PEER_EXCHANGE)) {
  180. btInteractive->setUTPexEnabled(true);
  181. }
  182. if(DHTSetup::initialized()) {
  183. btInteractive->setDHTEnabled(true);
  184. btInteractive->setLocalNode(DHTRegistry::getData().localNode);
  185. factory->setDHTEnabled(true);
  186. }
  187. }
  188. btInteractive->setUTMetadataRequestFactory(utMetadataRequestFactory);
  189. btInteractive->setUTMetadataRequestTracker(utMetadataRequestTracker);
  190. if(metadataGetMode) {
  191. btInteractive->enableMetadataGetMode();
  192. }
  193. btInteractive_ = btInteractive;
  194. // reverse depends
  195. factory->setBtMessageDispatcher(dispatcher);
  196. factory->setBtRequestFactory(reqFactory);
  197. factory->setPeerConnection(peerConnection);
  198. extensionMessageFactory->setBtMessageDispatcher(dispatcher);
  199. extensionMessageFactory->setBtMessageFactory(factory);
  200. if(metadataGetMode) {
  201. utMetadataRequestFactory->setDownloadContext
  202. (requestGroup_->getDownloadContext());
  203. utMetadataRequestFactory->setBtMessageDispatcher(dispatcher);
  204. utMetadataRequestFactory->setBtMessageFactory(factory);
  205. utMetadataRequestFactory->setPeer(getPeer());
  206. utMetadataRequestFactory->setUTMetadataRequestTracker
  207. (utMetadataRequestTracker);
  208. }
  209. getPeer()->allocateSessionResource
  210. (requestGroup_->getDownloadContext()->getPieceLength(),
  211. requestGroup_->getDownloadContext()->getTotalLength());
  212. getPeer()->setBtMessageDispatcher(dispatcher);
  213. btRuntime_->increaseConnections();
  214. requestGroup_->increaseNumCommand();
  215. }
  216. PeerInteractionCommand::~PeerInteractionCommand() {
  217. if(getPeer()->getCompletedLength() > 0) {
  218. pieceStorage_->subtractPieceStats(getPeer()->getBitfield(),
  219. getPeer()->getBitfieldLength());
  220. }
  221. getPeer()->releaseSessionResource();
  222. requestGroup_->decreaseNumCommand();
  223. btRuntime_->decreaseConnections();
  224. }
  225. bool PeerInteractionCommand::executeInternal() {
  226. setNoCheck(false);
  227. switch(sequence_) {
  228. case INITIATOR_SEND_HANDSHAKE:
  229. if(!getSocket()->isWritable(0)) {
  230. break;
  231. }
  232. disableWriteCheckSocket();
  233. setReadCheckSocket(getSocket());
  234. //socket->setBlockingMode();
  235. setTimeout(getOption()->getAsInt(PREF_BT_TIMEOUT));
  236. btInteractive_->initiateHandshake();
  237. sequence_ = INITIATOR_WAIT_HANDSHAKE;
  238. break;
  239. case INITIATOR_WAIT_HANDSHAKE: {
  240. if(btInteractive_->countPendingMessage() > 0) {
  241. btInteractive_->sendPendingMessage();
  242. if(btInteractive_->countPendingMessage() > 0) {
  243. break;
  244. }
  245. }
  246. BtMessageHandle handshakeMessage = btInteractive_->receiveHandshake();
  247. if(handshakeMessage.isNull()) {
  248. break;
  249. }
  250. btInteractive_->doPostHandshakeProcessing();
  251. sequence_ = WIRED;
  252. break;
  253. }
  254. case RECEIVER_WAIT_HANDSHAKE: {
  255. BtMessageHandle handshakeMessage =btInteractive_->receiveAndSendHandshake();
  256. if(handshakeMessage.isNull()) {
  257. break;
  258. }
  259. btInteractive_->doPostHandshakeProcessing();
  260. sequence_ = WIRED;
  261. break;
  262. }
  263. case WIRED:
  264. // See the comment for writable check below.
  265. disableWriteCheckSocket();
  266. btInteractive_->doInteractionProcessing();
  267. if(btInteractive_->countReceivedMessageInIteration() > 0) {
  268. updateKeepAlive();
  269. }
  270. if((getPeer()->amInterested() && !getPeer()->peerChoking()) ||
  271. btInteractive_->countOutstandingRequest() ||
  272. (getPeer()->peerInterested() && !getPeer()->amChoking())) {
  273. // Writable check to avoid slow seeding
  274. if(btInteractive_->isSendingMessageInProgress()) {
  275. setWriteCheckSocket(getSocket());
  276. }
  277. if(getDownloadEngine()->getRequestGroupMan()->
  278. doesOverallDownloadSpeedExceed() ||
  279. requestGroup_->doesDownloadSpeedExceed()) {
  280. disableReadCheckSocket();
  281. setNoCheck(true);
  282. } else {
  283. setReadCheckSocket(getSocket());
  284. }
  285. } else {
  286. disableReadCheckSocket();
  287. }
  288. break;
  289. }
  290. if(btInteractive_->countPendingMessage() > 0) {
  291. setNoCheck(true);
  292. }
  293. getDownloadEngine()->addCommand(this);
  294. return false;
  295. }
  296. // TODO this method removed when PeerBalancerCommand is implemented
  297. bool PeerInteractionCommand::prepareForNextPeer(time_t wait) {
  298. if(peerStorage_->isPeerAvailable() && btRuntime_->lessThanEqMinPeers()) {
  299. SharedHandle<Peer> peer = peerStorage_->getUnusedPeer();
  300. peer->usedBy(getDownloadEngine()->newCUID());
  301. PeerInitiateConnectionCommand* command =
  302. new PeerInitiateConnectionCommand
  303. (peer->usedBy(), requestGroup_, peer, getDownloadEngine(), btRuntime_);
  304. command->setPeerStorage(peerStorage_);
  305. command->setPieceStorage(pieceStorage_);
  306. getDownloadEngine()->addCommand(command);
  307. }
  308. return true;
  309. }
  310. void PeerInteractionCommand::onAbort() {
  311. btInteractive_->cancelAllPiece();
  312. peerStorage_->returnPeer(getPeer());
  313. }
  314. void PeerInteractionCommand::onFailure()
  315. {
  316. requestGroup_->setHaltRequested(true);
  317. }
  318. bool PeerInteractionCommand::exitBeforeExecute()
  319. {
  320. return btRuntime_->isHalt();
  321. }
  322. const SharedHandle<Option>& PeerInteractionCommand::getOption() const
  323. {
  324. return requestGroup_->getOption();
  325. }
  326. } // namespace aria2