/* */ #include "ReceiverMSEHandshakeCommand.h" #include "PeerReceiveHandshakeCommand.h" #include "PeerConnection.h" #include "DownloadEngine.h" #include "BtHandshakeMessage.h" #include "DlAbortEx.h" #include "Peer.h" #include "message.h" #include "Socket.h" #include "Logger.h" #include "prefs.h" #include "Option.h" #include "MSEHandshake.h" #include "ARC4Encryptor.h" #include "ARC4Decryptor.h" #include "RequestGroupMan.h" #include "BtRegistry.h" #include "DownloadContext.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "BtAnnounce.h" #include "BtRuntime.h" #include "BtProgressInfoFile.h" #include "ServerStatMan.h" #include "FileAllocationEntry.h" #include "CheckIntegrityEntry.h" namespace aria2 { ReceiverMSEHandshakeCommand::ReceiverMSEHandshakeCommand (cuid_t cuid, const SharedHandle& peer, DownloadEngine* e, const SharedHandle& s): PeerAbstractCommand(cuid, peer, e, s), _sequence(RECEIVER_IDENTIFY_HANDSHAKE), _mseHandshake(new MSEHandshake(cuid, s, e->getOption())) { setTimeout(e->getOption()->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); } ReceiverMSEHandshakeCommand::~ReceiverMSEHandshakeCommand() { delete _mseHandshake; } bool ReceiverMSEHandshakeCommand::exitBeforeExecute() { return getDownloadEngine()->isHaltRequested() || getDownloadEngine()->getRequestGroupMan()->downloadFinished(); } bool ReceiverMSEHandshakeCommand::executeInternal() { switch(_sequence) { case RECEIVER_IDENTIFY_HANDSHAKE: { MSEHandshake::HANDSHAKE_TYPE type = _mseHandshake->identifyHandshakeType(); switch(type) { case MSEHandshake::HANDSHAKE_NOT_YET: break; case MSEHandshake::HANDSHAKE_ENCRYPTED: _mseHandshake->initEncryptionFacility(false); _sequence = RECEIVER_WAIT_KEY; break; case MSEHandshake::HANDSHAKE_LEGACY: { if(getDownloadEngine()->getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { throw DL_ABORT_EX ("The legacy BitTorrent handshake is not acceptable by the" " preference."); } SharedHandle peerConnection (new PeerConnection(getCuid(), getSocket())); peerConnection->presetBuffer(_mseHandshake->getBuffer(), _mseHandshake->getBufferLength()); Command* c = new PeerReceiveHandshakeCommand(getCuid(), getPeer(), getDownloadEngine(), getSocket(), peerConnection); getDownloadEngine()->addCommand(c); return true; } default: throw DL_ABORT_EX("Not supported handshake type."); } break; } case RECEIVER_WAIT_KEY: { if(_mseHandshake->receivePublicKey()) { if(_mseHandshake->sendPublicKey()) { _sequence = RECEIVER_FIND_HASH_MARKER; } else { setWriteCheckSocket(getSocket()); _sequence = RECEIVER_SEND_KEY_PENDING; } } break; } case RECEIVER_SEND_KEY_PENDING: if(_mseHandshake->sendPublicKey()) { disableWriteCheckSocket(); _sequence = RECEIVER_FIND_HASH_MARKER; } break; case RECEIVER_FIND_HASH_MARKER: { if(_mseHandshake->findReceiverHashMarker()) { _sequence = RECEIVER_RECEIVE_PAD_C_LENGTH; } break; } case RECEIVER_RECEIVE_PAD_C_LENGTH: { std::vector > downloadContexts; getDownloadEngine()->getBtRegistry()->getAllDownloadContext (std::back_inserter(downloadContexts)); if(_mseHandshake->receiveReceiverHashAndPadCLength(downloadContexts)) { _sequence = RECEIVER_RECEIVE_PAD_C; } break; } case RECEIVER_RECEIVE_PAD_C: { if(_mseHandshake->receivePad()) { _sequence = RECEIVER_RECEIVE_IA_LENGTH; } break; } case RECEIVER_RECEIVE_IA_LENGTH: { if(_mseHandshake->receiveReceiverIALength()) { _sequence = RECEIVER_RECEIVE_IA; } break; } case RECEIVER_RECEIVE_IA: { if(_mseHandshake->receiveReceiverIA()) { if(_mseHandshake->sendReceiverStep2()) { createCommand(); return true; } else { setWriteCheckSocket(getSocket()); _sequence = RECEIVER_SEND_STEP2_PENDING; } } break; } case RECEIVER_SEND_STEP2_PENDING: if(_mseHandshake->sendReceiverStep2()) { disableWriteCheckSocket(); createCommand(); return true; } break; } getDownloadEngine()->addCommand(this); return false; } void ReceiverMSEHandshakeCommand::createCommand() { SharedHandle peerConnection (new PeerConnection(getCuid(), getSocket())); if(_mseHandshake->getNegotiatedCryptoType() == MSEHandshake::CRYPTO_ARC4) { peerConnection->enableEncryption(_mseHandshake->getEncryptor(), _mseHandshake->getDecryptor()); } if(_mseHandshake->getIALength() > 0) { peerConnection->presetBuffer(_mseHandshake->getIA(), _mseHandshake->getIALength()); } // TODO add _mseHandshake->getInfoHash() to PeerReceiveHandshakeCommand // as a hint. If this info hash and one in BitTorrent Handshake does not // match, then drop connection. Command* c = new PeerReceiveHandshakeCommand(getCuid(), getPeer(), getDownloadEngine(), getSocket(), peerConnection); getDownloadEngine()->addCommand(c); } } // namespace aria2