void UDPListener::sendIMAliveMessage() { Protos::Core::IMAlive IMAliveMessage; IMAliveMessage.set_version(PROTOCOL_VERSION); ProtoHelper::setStr(IMAliveMessage, &Protos::Core::IMAlive::set_core_version, Common::Global::getVersionFull()); IMAliveMessage.set_port(this->UNICAST_PORT); Common::ProtoHelper::setStr(IMAliveMessage, &Protos::Core::IMAlive::set_nick, this->peerManager->getNick()); IMAliveMessage.set_amount(this->fileManager->getAmount()); IMAliveMessage.set_download_rate(this->downloadManager->getDownloadRate()); IMAliveMessage.set_upload_rate(this->uploadManager->getUploadRate()); this->currentIMAliveTag = this->mtrand.randInt(); this->currentIMAliveTag <<= 32; this->currentIMAliveTag |= this->mtrand.randInt(); IMAliveMessage.set_tag(this->currentIMAliveTag); static const quint32 NUMBER_OF_HASHES_TO_SEND = SETTINGS.get<quint32>("number_of_hashes_sent_imalive"); this->currentChunkDownloads = this->downloadManager->getUnfinishedChunks(NUMBER_OF_HASHES_TO_SEND); IMAliveMessage.mutable_chunk()->Reserve(this->currentChunkDownloads.size()); for (QListIterator< QSharedPointer<DM::IChunkDownload> > i(this->currentChunkDownloads); i.hasNext();) { IMAliveMessage.add_chunk()->set_hash(i.next()->getHash().getData(), Common::Hash::HASH_SIZE); } this->send(Common::MessageHeader::CORE_IM_ALIVE, IMAliveMessage); }
void UDPListener::sendIMAliveMessage() { Protos::Core::IMAlive IMAliveMessage; IMAliveMessage.set_version(PROTOCOL_VERSION); Common::ProtoHelper::setStr(IMAliveMessage, &Protos::Core::IMAlive::set_core_version, Common::Global::getVersionFull()); IMAliveMessage.set_port(this->UNICAST_PORT); const QString& nick = this->peerManager->getSelf()->getNick(); Common::ProtoHelper::setStr(IMAliveMessage, &Protos::Core::IMAlive::set_nick, nick.length() > MAX_NICK_LENGTH ? nick.left(MAX_NICK_LENGTH) : nick); IMAliveMessage.set_amount(this->fileManager->getAmount()); IMAliveMessage.set_download_rate(this->downloadManager->getDownloadRate()); IMAliveMessage.set_upload_rate(this->uploadManager->getUploadRate()); this->currentIMAliveTag = this->mtrand.randInt(); this->currentIMAliveTag <<= 32; this->currentIMAliveTag |= this->mtrand.randInt(); IMAliveMessage.set_tag(this->currentIMAliveTag); // We fill the rest of the message with a maximum of needed hashes. static const quint32 MAX_IMALIVE_THROUGHPUT = SETTINGS.get<quint32>("max_imalive_throughput"); static const int AVERAGE_FIXED_SIZE = 100; // [Byte]. Header size + information in the 'IMAlive' message without the hashes. static const quint32 IMALIVE_PERIOD = SETTINGS.get<quint32>("peer_imalive_period") / 1000; // [s] static const int FIXED_RATE_PER_PEER = AVERAGE_FIXED_SIZE / IMALIVE_PERIOD; // [Byte/s] static const int HASH_SIZE = Common::Hash::HASH_SIZE + 4; // "4" is the overhead added by protobuff for each hash. const int numberOfPeers = this->peerManager->getNbOfPeers(); const int maxNumberOfHashesToSend = numberOfPeers == 0 ? std::numeric_limits<int>::max() : IMALIVE_PERIOD * (MAX_IMALIVE_THROUGHPUT - numberOfPeers * FIXED_RATE_PER_PEER) / (numberOfPeers * HASH_SIZE); int numberOfHashesToSend = (this->MAX_UDP_DATAGRAM_PAYLOAD_SIZE - IMAliveMessage.ByteSize() - Common::MessageHeader::HEADER_SIZE) / HASH_SIZE; if (numberOfHashesToSend > maxNumberOfHashesToSend) numberOfHashesToSend = maxNumberOfHashesToSend; // The requested hashes method alternates from the first hashes and the oldest hashes. // We are trying to have the knowledge about who has which chunk for the whole download queue (IDownloadManager::getTheOldestUnfinishedChunks(..)) // and for the chunks we want to download first (IDownloadManager::getTheFirstUnfinishedChunks(..)). switch (this->nextHashRequestType) { case FIRST_HASHES: this->currentChunkDownloaders = this->downloadManager->getTheFirstUnfinishedChunks(numberOfHashesToSend); this->nextHashRequestType = OLDEST_HASHES; break; case OLDEST_HASHES: this->currentChunkDownloaders = this->downloadManager->getTheOldestUnfinishedChunks(numberOfHashesToSend); this->nextHashRequestType = FIRST_HASHES; break; } IMAliveMessage.mutable_chunk()->Reserve(this->currentChunkDownloaders.size()); for (QListIterator<QSharedPointer<DM::IChunkDownloader>> i(this->currentChunkDownloaders); i.hasNext();) { QSharedPointer<DM::IChunkDownloader> chunkDownloader = i.next(); IMAliveMessage.add_chunk()->set_hash(chunkDownloader->getHash().getData(), Common::Hash::HASH_SIZE); // If we already have the chunk . . . QSharedPointer<FM::IChunk> chunk = this->fileManager->getChunk(chunkDownloader->getHash()); if (!chunk.isNull() && chunk->isComplete()) chunkDownloader->addPeer(this->peerManager->getSelf()); else chunkDownloader->rmPeer(this->peerManager->getSelf()); } emit IMAliveMessageToBeSend(IMAliveMessage); this->send(Common::MessageHeader::CORE_IM_ALIVE, IMAliveMessage); }