/* */ #include "InitiatorMSEHandshakeCommand.h" #include "PeerInitiateConnectionCommand.h" #include "PeerInteractionCommand.h" #include "DownloadEngine.h" #include "DlAbortEx.h" #include "message.h" #include "prefs.h" #include "Socket.h" #include "Logger.h" #include "Peer.h" #include "PeerConnection.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "Option.h" #include "MSEHandshake.h" #include "ARC4Encryptor.h" #include "ARC4Decryptor.h" #include "RequestGroup.h" #include "DownloadContext.h" #include "bittorrent_helper.h" #include "util.h" #include "RequestGroupMan.h" #include "FileAllocationEntry.h" #include "CheckIntegrityEntry.h" #include "ServerStatMan.h" namespace aria2 { InitiatorMSEHandshakeCommand::InitiatorMSEHandshakeCommand (cuid_t cuid, RequestGroup* requestGroup, const SharedHandle& p, DownloadEngine* e, const SharedHandle& btRuntime, const SharedHandle& s): PeerAbstractCommand(cuid, p, e, s), _requestGroup(requestGroup), _btRuntime(btRuntime), _sequence(INITIATOR_SEND_KEY), _mseHandshake(new MSEHandshake(cuid, s, getOption().get())) { disableReadCheckSocket(); setWriteCheckSocket(getSocket()); setTimeout(getOption()->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); _btRuntime->increaseConnections(); _requestGroup->increaseNumCommand(); } InitiatorMSEHandshakeCommand::~InitiatorMSEHandshakeCommand() { _requestGroup->decreaseNumCommand(); _btRuntime->decreaseConnections(); delete _mseHandshake; } bool InitiatorMSEHandshakeCommand::executeInternal() { switch(_sequence) { case INITIATOR_SEND_KEY: { if(!getSocket()->isWritable(0)) { break; } disableWriteCheckSocket(); setReadCheckSocket(getSocket()); //socket->setBlockingMode(); setTimeout(getOption()->getAsInt(PREF_BT_TIMEOUT)); _mseHandshake->initEncryptionFacility(true); if(_mseHandshake->sendPublicKey()) { _sequence = INITIATOR_WAIT_KEY; } else { setWriteCheckSocket(getSocket()); _sequence = INITIATOR_SEND_KEY_PENDING; } break; } case INITIATOR_SEND_KEY_PENDING: if(_mseHandshake->sendPublicKey()) { disableWriteCheckSocket(); _sequence = INITIATOR_WAIT_KEY; } break; case INITIATOR_WAIT_KEY: { if(_mseHandshake->receivePublicKey()) { _mseHandshake->initCipher (bittorrent::getInfoHash(_requestGroup->getDownloadContext()));; if(_mseHandshake->sendInitiatorStep2()) { _sequence = INITIATOR_FIND_VC_MARKER; } else { setWriteCheckSocket(getSocket()); _sequence = INITIATOR_SEND_STEP2_PENDING; } } break; } case INITIATOR_SEND_STEP2_PENDING: if(_mseHandshake->sendInitiatorStep2()) { disableWriteCheckSocket(); _sequence = INITIATOR_FIND_VC_MARKER; } break; case INITIATOR_FIND_VC_MARKER: { if(_mseHandshake->findInitiatorVCMarker()) { _sequence = INITIATOR_RECEIVE_PAD_D_LENGTH; } break; } case INITIATOR_RECEIVE_PAD_D_LENGTH: { if(_mseHandshake->receiveInitiatorCryptoSelectAndPadDLength()) { _sequence = INITIATOR_RECEIVE_PAD_D; } break; } case INITIATOR_RECEIVE_PAD_D: { if(_mseHandshake->receivePad()) { SharedHandle peerConnection (new PeerConnection(getCuid(), getSocket())); if(_mseHandshake->getNegotiatedCryptoType() == MSEHandshake::CRYPTO_ARC4){ peerConnection->enableEncryption(_mseHandshake->getEncryptor(), _mseHandshake->getDecryptor()); } PeerInteractionCommand* c = new PeerInteractionCommand (getCuid(), _requestGroup, getPeer(), getDownloadEngine(), _btRuntime, _pieceStorage, _peerStorage, getSocket(), PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE, peerConnection); getDownloadEngine()->addCommand(c); return true; } break; } } getDownloadEngine()->addCommand(this); return false; } bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) { if(getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { if(getLogger()->info()) { getLogger()->info ("CUID#%s - Establishing connection using legacy BitTorrent" " handshake is disabled by preference.", util::itos(getCuid()).c_str()); } if(_peerStorage->isPeerAvailable() && _btRuntime->lessThanEqMinPeers()) { SharedHandle peer = _peerStorage->getUnusedPeer(); peer->usedBy(getDownloadEngine()->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, getDownloadEngine(), _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); getDownloadEngine()->addCommand(command); } return true; } else { // try legacy BitTorrent handshake if(getLogger()->info()) { getLogger()->info("CUID#%s - Retry using legacy BitTorrent handshake.", util::itos(getCuid()).c_str()); } PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(getCuid(), _requestGroup, getPeer(), getDownloadEngine(), _btRuntime, false); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); getDownloadEngine()->addCommand(command); return true; } } void InitiatorMSEHandshakeCommand::onAbort() { if(getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { _peerStorage->returnPeer(getPeer()); } } bool InitiatorMSEHandshakeCommand::exitBeforeExecute() { return _btRuntime->isHalt(); } void InitiatorMSEHandshakeCommand::setPeerStorage (const SharedHandle& peerStorage) { _peerStorage = peerStorage; } void InitiatorMSEHandshakeCommand::setPieceStorage (const SharedHandle& pieceStorage) { _pieceStorage = pieceStorage; } const SharedHandle