/* */ #include "PeerListenCommand.h" #include #include #include "DownloadEngine.h" #include "Peer.h" #include "RequestGroupMan.h" #include "RecoverableException.h" #include "message.h" #include "ReceiverMSEHandshakeCommand.h" #include "Logger.h" #include "LogFactory.h" #include "Socket.h" #include "SimpleRandomizer.h" #include "util.h" #include "fmt.h" namespace aria2 { PeerListenCommand::PeerListenCommand (cuid_t cuid, DownloadEngine* e, int family) : Command(cuid), e_(e), family_(family) {} PeerListenCommand::~PeerListenCommand() {} bool PeerListenCommand::bindPort(uint16_t& port, IntSequence& seq) { socket_.reset(new SocketCore()); std::vector randPorts = seq.flush(); std::random_shuffle(randPorts.begin(), randPorts.end(), *SimpleRandomizer::getInstance().get()); for(std::vector::const_iterator portItr = randPorts.begin(), eoi = randPorts.end(); portItr != eoi; ++portItr) { if(!(0 < (*portItr) && (*portItr) <= 65535)) { continue; } port = (*portItr); try { socket_->bind(A2STR::NIL, port, family_); socket_->beginListen(); socket_->setNonBlockingMode(); A2_LOG_NOTICE(fmt("IPv%d BitTorrent: listening to port %d", family_ == AF_INET?4:6, port)); return true; } catch(RecoverableException& ex) { A2_LOG_ERROR(fmt("Failed to setup IPv%d BitTorrent server socket", family_ == AF_INET?4:6)); A2_LOG_ERROR_EX(fmt(MSG_BIND_FAILURE, getCuid(), port), ex); socket_->closeConnection(); } } return false; } uint16_t PeerListenCommand::getPort() const { if(!socket_) { return 0; } else { std::pair addr; socket_->getAddrInfo(addr); return addr.second; } } bool PeerListenCommand::execute() { if(e_->isHaltRequested() || e_->getRequestGroupMan()->downloadFinished()) { return true; } for(int i = 0; i < 3 && socket_->isReadable(0); ++i) { SocketHandle peerSocket; try { peerSocket.reset(socket_->acceptConnection()); std::pair peerInfo; peerSocket->getPeerInfo(peerInfo); peerSocket->setNonBlockingMode(); SharedHandle peer(new Peer(peerInfo.first, peerInfo.second, true)); cuid_t cuid = e_->newCUID(); Command* command = new ReceiverMSEHandshakeCommand(cuid, peer, e_, peerSocket); e_->addCommand(command); A2_LOG_DEBUG(fmt("Accepted the connection from %s:%u.", peer->getIPAddress().c_str(), peer->getPort())); A2_LOG_DEBUG(fmt("Added CUID#%lld to receive BitTorrent/MSE handshake.", cuid)); } catch(RecoverableException& ex) { A2_LOG_DEBUG_EX(fmt(MSG_ACCEPT_FAILURE, getCuid()), ex); } } e_->addCommand(this); return false; } } // namespace aria2