/** * 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)); } } }
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)); } } }
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())); } } }