/* */ #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" namespace aria2 { ReceiverMSEHandshakeCommand::ReceiverMSEHandshakeCommand (int32_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->option)) { setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT)); } ReceiverMSEHandshakeCommand::~ReceiverMSEHandshakeCommand() { delete _mseHandshake; } bool ReceiverMSEHandshakeCommand::exitBeforeExecute() { return e->isHaltRequested() || e->_requestGroupMan->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(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { throw DlAbortEx("The legacy BitTorrent handshake is not acceptable by the preference."); } SharedHandle peerConnection (new PeerConnection(cuid, socket, e->option)); peerConnection->presetBuffer(_mseHandshake->getBuffer(), _mseHandshake->getBufferLength()); Command* c = new PeerReceiveHandshakeCommand(cuid, peer, e, socket, peerConnection); e->commands.push_back(c); return true; } default: throw DlAbortEx("Not supported handshake type."); } break; } case RECEIVER_WAIT_KEY: { if(_mseHandshake->receivePublicKey()) { _mseHandshake->sendPublicKey(); _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: { if(_mseHandshake->receiveReceiverHashAndPadCLength()) { _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()) { _mseHandshake->sendReceiverStep2(); SharedHandle peerConnection (new PeerConnection(cuid, socket, e->option)); 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(cuid, peer, e, socket, peerConnection); e->commands.push_back(c); return true; } break; } } e->commands.push_back(this); return false; } } // namespace aria2