Beispiel #1
0
/**
  * Function called when data is recevied by the socket : The corresponding proto is created and the coresponding event is rised.
  */
void UDPListener::processPendingUnicastDatagrams()
{
   while (this->unicastSocket.hasPendingDatagrams())
   {
      QHostAddress peerAddress;
      const Common::MessageHeader& header =  UDPListener::readDatagramToBuffer(this->unicastSocket, peerAddress);
      if (header.isNull())
         continue;

      switch (header.getType())
      {
      case Common::MessageHeader::CORE_CHUNKS_OWNED:
         {
            Protos::Core::ChunksOwned chunksOwnedMessage;
            chunksOwnedMessage.ParseFromArray(this->bodyBuffer, header.getSize());

            if (chunksOwnedMessage.tag() != this->currentIMAliveTag)
            {
               L_WARN(QString("ChunksOwned : tag (%1) doesn't match current tag (%2)").arg(chunksOwnedMessage.tag()).arg(currentIMAliveTag));
               continue;
            }

            if (chunksOwnedMessage.chunk_state_size() != this->currentChunkDownloads.size())
            {
               L_WARN(QString("ChunksOwned : The size (%1) doesn't match the expected one (%2)").arg(chunksOwnedMessage.chunk_state_size()).arg(this->currentChunkDownloads.size()));
               continue;
            }

            for (int i = 0; i < chunksOwnedMessage.chunk_state_size(); i++)
            {
               if (chunksOwnedMessage.chunk_state(i))
                  this->currentChunkDownloads[i]->addPeerID(header.getSenderID());
               else
                  this->currentChunkDownloads[i]->rmPeerID(header.getSenderID());
            }
         }
         break;

      case Common::MessageHeader::CORE_FIND_RESULT:
         {
            Protos::Common::FindResult findResultMessage;
            findResultMessage.ParseFromArray(this->bodyBuffer, header.getSize());
            findResultMessage.mutable_peer_id()->set_hash(header.getSenderID().getData(), Common::Hash::HASH_SIZE);
            emit newFindResultMessage(findResultMessage);
         }
         break;

      default:
         L_WARN(QString("Unkown header type from unicast socket : %1").arg(header.getType(), 0, 16));
      }
   }
}
Beispiel #2
0
void UDPListener::processPendingMulticastDatagrams()
{
   while (this->multicastSocket.hasPendingDatagrams())
   {
      QHostAddress peerAddress;
      const Common::MessageHeader& header =  UDPListener::readDatagramToBuffer(this->multicastSocket, peerAddress);
      if (header.isNull())
         continue;

      switch (header.getType())
      {
      case Common::MessageHeader::CORE_IM_ALIVE:
         {
            Protos::Core::IMAlive IMAliveMessage;
            const bool readOk = IMAliveMessage.ParseFromArray(this->bodyBuffer, header.getSize());

            if (!readOk)
            {
               L_WARN(QString("Unable to read the IMAlive message from peer %1 %2").arg(header.getSenderID().toStr()).arg(peerAddress.toString()));
               break;
            }
            else if (IMAliveMessage.version() != PROTOCOL_VERSION) // If the protocol version doesn't match we don't add the peer.
            {
               L_WARN(
                  QString("The peer %1 %2 %3 doesn't have the same protocol version (%4) as us (%5). It will be ignored.")
                     .arg(Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::nick))
                     .arg(header.getSenderID().toStr())
                     .arg(peerAddress.toString())
                     .arg(IMAliveMessage.version())
                     .arg(PROTOCOL_VERSION)
               );
               break;
            }

            this->peerManager->updatePeer(
               header.getSenderID(),
               peerAddress,
               IMAliveMessage.port(),
               Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::nick),
               IMAliveMessage.amount(),
               Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::core_version)
            );

            if (IMAliveMessage.chunk_size() > 0)
            {
               QList<Common::Hash> hashes;
               hashes.reserve(IMAliveMessage.chunk_size());
               for (int i = 0; i < IMAliveMessage.chunk_size(); i++)
                  hashes << IMAliveMessage.chunk(i).hash();

               QBitArray bitArray = this->fileManager->haveChunks(hashes);

               if (!bitArray.isNull()) // If we own at least one chunk we reply with a CHUNKS_OWNED message.
               {
                  Protos::Core::ChunksOwned chunkOwnedMessage;
                  chunkOwnedMessage.set_tag(IMAliveMessage.tag());
                  chunkOwnedMessage.mutable_chunk_state()->Reserve(bitArray.size());
                  for (int i = 0; i < bitArray.size(); i++)
                     chunkOwnedMessage.add_chunk_state(bitArray[i]);
                  this->send(Common::MessageHeader::CORE_CHUNKS_OWNED, header.getSenderID(), chunkOwnedMessage);
               }
            }
         }
         break;

      case Common::MessageHeader::CORE_CHAT_MESSAGE:
         {
            Protos::Core::ChatMessage chatMessage;
            chatMessage.ParseFromArray(this->bodyBuffer, header.getSize());
            emit newChatMessage(header.getSenderID(), chatMessage);
         }
         break;

      case Common::MessageHeader::CORE_FIND: // Find.
         {
            Protos::Core::Find findMessage;
            findMessage.ParseFromArray(this->bodyBuffer, header.getSize());

            QList<Protos::Common::FindResult> results =
               this->fileManager->find(
                  Common::ProtoHelper::getStr(findMessage, &Protos::Core::Find::pattern),
                  SETTINGS.get<quint32>("max_number_of_search_result_to_send"),
                  SETTINGS.get<quint32>("max_udp_datagram_size") - Common::MessageHeader::HEADER_SIZE
               );

            for (QMutableListIterator<Protos::Common::FindResult> i(results); i.hasNext();)
            {
               Protos::Common::FindResult& result = i.next();
               result.set_tag(findMessage.tag());
               this->send(Common::MessageHeader::CORE_FIND_RESULT, header.getSenderID(), result);
            }
         }
         break;

      default:
         L_WARN(QString("Unkown header type from multicast socket : %1").arg(header.getType(), 0, 16));
      }
   }
}
Beispiel #3
0
void UDPListener::processPendingMulticastDatagrams()
{
   while (this->multicastSocket.hasPendingDatagrams())
   {
      QHostAddress peerAddress;
      const Common::MessageHeader& header = this->readDatagramToBuffer(this->multicastSocket, peerAddress);
      if (header.isNull())
         continue;

      try
      {
         const Common::Message& message = Common::Message::readMessageBody(header, this->bodyBuffer);

         switch (header.getType())
         {
         case Common::MessageHeader::CORE_IM_ALIVE:
            {
               const Protos::Core::IMAlive& IMAliveMessage = message.getMessage<Protos::Core::IMAlive>();

               if (IMAliveMessage.version() != PROTOCOL_VERSION) // If the protocol version doesn't match we don't add the peer.
               {
                  L_WARN(
                     QString("The peer %1 %2 %3 doesn't have the same protocol version (%4) as us (%5). It will be ignored.")
                        .arg(Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::nick))
                        .arg(header.getSenderID().toStr())
                        .arg(peerAddress.toString())
                        .arg(IMAliveMessage.version())
                        .arg(PROTOCOL_VERSION)
                  );
                  break;
               }

               this->peerManager->updatePeer(
                  header.getSenderID(),
                  peerAddress,
                  IMAliveMessage.port(),
                  Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::nick),
                  IMAliveMessage.amount(),
                  Common::ProtoHelper::getStr(IMAliveMessage, &Protos::Core::IMAlive::core_version),
                  IMAliveMessage.download_rate(),
                  IMAliveMessage.upload_rate()
               );

               if (IMAliveMessage.chunk_size() > 0)
               {
                  QList<Common::Hash> hashes;
                  hashes.reserve(IMAliveMessage.chunk_size());
                  for (int i = 0; i < IMAliveMessage.chunk_size(); i++)
                     hashes << IMAliveMessage.chunk(i).hash();

                  const QBitArray& bitArray = this->fileManager->haveChunks(hashes);

                  if (!bitArray.isNull()) // If we own at least one chunk we reply with a CHUNKS_OWNED message.
                  {
                     Protos::Core::ChunksOwned chunkOwnedMessage;
                     chunkOwnedMessage.set_tag(IMAliveMessage.tag());
                     chunkOwnedMessage.mutable_chunk_state()->Reserve(bitArray.size());
                     for (int i = 0; i < bitArray.size(); i++)
                        chunkOwnedMessage.add_chunk_state(bitArray[i]);
                     this->send(Common::MessageHeader::CORE_CHUNKS_OWNED, chunkOwnedMessage, header.getSenderID());
                  }
               }
            }
            break;

         case Common::MessageHeader::CORE_GOODBYE:
            this->peerManager->removePeer(header.getSenderID(), peerAddress);
            break;

         case Common::MessageHeader::CORE_FIND:
            {
               const Protos::Core::Find& findMessage = message.getMessage<Protos::Core::Find>();
               QList<Protos::Common::FindResult> results =
                  this->fileManager->find(
                     Common::ProtoHelper::getStr(findMessage, &Protos::Core::Find::pattern),
                     SETTINGS.get<quint32>("max_number_of_search_result_to_send"),
                     this->MAX_UDP_DATAGRAM_PAYLOAD_SIZE - Common::MessageHeader::HEADER_SIZE
                  );

               for (QMutableListIterator<Protos::Common::FindResult> i(results); i.hasNext();)
               {
                  Protos::Common::FindResult& result = i.next();
                  result.set_tag(findMessage.tag());
                  this->send(Common::MessageHeader::CORE_FIND_RESULT, result, header.getSenderID());
               }
            }
            break;

         default:; // Ignore other messages.
         }

         emit received(message);
      }
      catch(Common::ReadErrorException&)
      {
         L_WARN(QString("Unable to read a multicast message from peer %1 %2").arg(header.getSenderID().toStr()).arg(peerAddress.toString()));
      }
   }
}