/* */ #include "PeerListenCommand.h" #include #include #include #include "DownloadEngine.h" #include "Peer.h" #include "RequestGroupMan.h" #include "RecoverableException.h" #include "message.h" #include "ReceiverMSEHandshakeCommand.h" #include "Logger.h" #include "Socket.h" #include "SimpleRandomizer.h" #include "FileEntry.h" namespace aria2 { unsigned int PeerListenCommand::__numInstance = 0; PeerListenCommand* PeerListenCommand::__instance = 0; PeerListenCommand::PeerListenCommand(int32_t cuid, DownloadEngine* e): Command(cuid), e(e), _lowestSpeedLimit(20*1024) { ++__numInstance; } PeerListenCommand::~PeerListenCommand() { --__numInstance; } bool PeerListenCommand::bindPort(uint16_t& port, IntSequence& seq) { socket.reset(new SocketCore()); std::deque randPorts = seq.flush(); std::random_shuffle(randPorts.begin(), randPorts.end(), *SimpleRandomizer::getInstance().get()); for(std::deque::const_iterator portItr = randPorts.begin(); portItr != randPorts.end(); ++portItr) { if(!(0 < (*portItr) && (*portItr) <= 65535)) { continue; } port = (*portItr); try { socket->bind(port); socket->beginListen(); socket->setNonBlockingMode(); logger->info(MSG_LISTENING_PORT, cuid, port); return true; } catch(RecoverableException& ex) { logger->error(MSG_BIND_FAILURE, ex, cuid, port); socket->closeConnection(); } } return false; } uint16_t PeerListenCommand::getPort() const { if(socket.isNull()) { return 0; } else { std::pair addr; socket->getAddrInfo(addr); return addr.second; } } bool PeerListenCommand::execute() { if(e->isHaltRequested() || e->_requestGroupMan->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(); PeerHandle peer(new Peer(peerInfo.first, peerInfo.second, true)); int32_t cuid = e->newCUID(); Command* command = new ReceiverMSEHandshakeCommand(cuid, peer, e, peerSocket); e->commands.push_back(command); logger->debug("Accepted the connection from %s:%u.", peer->ipaddr.c_str(), peer->port); logger->debug("Added CUID#%d to receive BitTorrent/MSE handshake.", cuid); } catch(RecoverableException& ex) { logger->debug(MSG_ACCEPT_FAILURE, ex, cuid); } } e->commands.push_back(this); return false; } PeerListenCommand* PeerListenCommand::getInstance(DownloadEngine* e) { if(__numInstance == 0) { __instance = new PeerListenCommand(e->newCUID(), e); } return __instance; } } // namespace aria2