/* */ #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 "BtContext.h" #include "BtRuntime.h" #include "PeerStorage.h" #include "PieceStorage.h" #include "Option.h" #include "MSEHandshake.h" #include "ARC4Encryptor.h" #include "ARC4Decryptor.h" namespace aria2 { InitiatorMSEHandshakeCommand::InitiatorMSEHandshakeCommand (int32_t cuid, RequestGroup* requestGroup, const SharedHandle& p, DownloadEngine* e, const SharedHandle& btContext, const SharedHandle& btRuntime, const SharedHandle& s): PeerAbstractCommand(cuid, p, e, s), RequestGroupAware(requestGroup), _btContext(btContext), _btRuntime(btRuntime), _sequence(INITIATOR_SEND_KEY), _mseHandshake(new MSEHandshake(cuid, socket, e->option)) { disableReadCheckSocket(); setWriteCheckSocket(socket); setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); _btRuntime->increaseConnections(); } InitiatorMSEHandshakeCommand::~InitiatorMSEHandshakeCommand() { _btRuntime->decreaseConnections(); delete _mseHandshake; } bool InitiatorMSEHandshakeCommand::executeInternal() { switch(_sequence) { case INITIATOR_SEND_KEY: { if(!socket->isWritable(0)) { break; } disableWriteCheckSocket(); setReadCheckSocket(socket); //socket->setBlockingMode(); setTimeout(e->option->getAsInt(PREF_BT_TIMEOUT)); _mseHandshake->initEncryptionFacility(true); if(_mseHandshake->sendPublicKey()) { _sequence = INITIATOR_WAIT_KEY; } else { setWriteCheckSocket(socket); _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(_btContext->getInfoHash()); if(_mseHandshake->sendInitiatorStep2()) { _sequence = INITIATOR_FIND_VC_MARKER; } else { setWriteCheckSocket(socket); _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(cuid, socket, e->option)); if(_mseHandshake->getNegotiatedCryptoType() == MSEHandshake::CRYPTO_ARC4) { peerConnection->enableEncryption(_mseHandshake->getEncryptor(), _mseHandshake->getDecryptor()); } PeerInteractionCommand* c = new PeerInteractionCommand(cuid, _requestGroup, peer, e, _btContext, _btRuntime, _pieceStorage, socket, PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE, peerConnection); c->setPeerStorage(_peerStorage); e->commands.push_back(c); return true; } break; } } e->commands.push_back(this); return false; } bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) { if(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { logger->info("CUID#%d - Establishing connection using legacy BitTorrent handshake is disabled by preference.", cuid); if(_peerStorage->isPeerAvailable() && _btRuntime->lessThanEqMinPeers()) { SharedHandle peer = _peerStorage->getUnusedPeer(); peer->usedBy(e->newCUID()); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e, _btContext, _btRuntime); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); } return true; } else { // try legacy BitTorrent handshake logger->info("CUID#%d - Retry using legacy BitTorrent handshake.", cuid); PeerInitiateConnectionCommand* command = new PeerInitiateConnectionCommand(cuid, _requestGroup, peer, e, _btContext, _btRuntime, false); command->setPeerStorage(_peerStorage); command->setPieceStorage(_pieceStorage); e->commands.push_back(command); return true; } } void InitiatorMSEHandshakeCommand::onAbort() { if(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { _peerStorage->returnPeer(peer); } } bool InitiatorMSEHandshakeCommand::exitBeforeExecute() { return _btRuntime->isHalt(); } void InitiatorMSEHandshakeCommand::setPeerStorage (const SharedHandle& peerStorage) { _peerStorage = peerStorage; } void InitiatorMSEHandshakeCommand::setPieceStorage (const SharedHandle& pieceStorage) { _pieceStorage = pieceStorage; } } // namespace aria2