Example #1
0
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);
}
Example #2
0
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);
}