/** Selects the appropriate piece to download and requests it to the remote_peer */ void Peer::requestNewPieceTo(Connection* remote_peer) { int piece = selectPieceToDownload(remote_peer); if (piece != -1) { current_pieces |= (1U << (unsigned int)piece); sendRequestTo(remote_peer, piece); } }
/*! Send and encode a request to a specific receptor. \sa vpNetwork::sendRequest() \sa vpNetwork::sendAndEncodeRequest() \sa vpNetwork::sendAndEncodeRequestTo() \sa vpNetwork::send() \sa vpNetwork::sendTo() \param req : Request to send. \param dest : Index of the receptor receiving the request. \return The number of bytes that have been sent, -1 if an error occured. */ int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest) { req.encode(); return sendRequestTo(req,dest); }
void Peer::handleMessage() { const char* type_names[10] = {"HANDSHAKE", "CHOKE", "UNCHOKE", "INTERESTED", "NOTINTERESTED", "HAVE", "BITFIELD", "REQUEST", "PIECE", "CANCEL"}; XBT_DEBUG("Received a %s message from %s", type_names[message->type], message->return_mailbox->get_cname()); auto known_peer = connected_peers.find(message->peer_id); Connection* remote_peer = (known_peer == connected_peers.end()) ? nullptr : known_peer->second; xbt_assert(remote_peer != nullptr || message->type == MESSAGE_HANDSHAKE, "The impossible did happened: A not-in-our-list peer sent us a message."); switch (message->type) { case MESSAGE_HANDSHAKE: // Check if the peer is in our connection list. if (remote_peer == nullptr) { XBT_DEBUG("This peer %d was unknown, answer to its handshake", message->peer_id); connected_peers[message->peer_id] = new Connection(message->peer_id); sendMessage(message->return_mailbox, MESSAGE_HANDSHAKE, MESSAGE_HANDSHAKE_SIZE); } // Send our bitfield to the peer sendBitfield(message->return_mailbox); break; case MESSAGE_BITFIELD: // Update the pieces list updatePiecesCountFromBitfield(message->bitfield); // Store the bitfield remote_peer->bitfield = message->bitfield; xbt_assert(not remote_peer->am_interested, "Should not be interested at first"); if (isInterestedBy(remote_peer)) { remote_peer->am_interested = true; sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE); } break; case MESSAGE_INTERESTED: // Update the interested state of the peer. remote_peer->interested = true; updateActivePeersSet(remote_peer); break; case MESSAGE_NOTINTERESTED: remote_peer->interested = false; updateActivePeersSet(remote_peer); break; case MESSAGE_UNCHOKE: xbt_assert(remote_peer->choked_download); remote_peer->choked_download = false; // Send requests to the peer, since it has unchoked us if (remote_peer->am_interested) requestNewPieceTo(remote_peer); break; case MESSAGE_CHOKE: xbt_assert(not remote_peer->choked_download); remote_peer->choked_download = true; if (remote_peer->current_piece != -1) removeCurrentPiece(remote_peer, remote_peer->current_piece); break; case MESSAGE_HAVE: XBT_DEBUG("\t for piece %d", message->piece); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong HAVE message received"); remote_peer->bitfield = remote_peer->bitfield | (1U << static_cast<unsigned int>(message->piece)); pieces_count[message->piece]++; // If the piece is in our pieces, we tell the peer that we are interested. if (not remote_peer->am_interested && hasNotPiece(message->piece)) { remote_peer->am_interested = true; sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE); if (not remote_peer->choked_download) requestNewPieceTo(remote_peer); } break; case MESSAGE_REQUEST: xbt_assert(remote_peer->interested); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong HAVE message received"); if (not remote_peer->choked_upload) { XBT_DEBUG("\t for piece %d (%d,%d)", message->piece, message->block_index, message->block_index + message->block_length); if (not hasNotPiece(message->piece)) { sendPiece(message->return_mailbox, message->piece, message->block_index, message->block_length); } } else { XBT_DEBUG("\t for piece %d but he is choked.", message->peer_id); } break; case MESSAGE_PIECE: XBT_DEBUG(" \t for piece %d (%d,%d)", message->piece, message->block_index, message->block_index + message->block_length); xbt_assert(not remote_peer->choked_download); xbt_assert(remote_peer->am_interested || ENABLE_END_GAME_MODE, "Can't received a piece if I'm not interested without end-game mode!" "piece (%d) bitfield (%u) remote bitfield (%u)", message->piece, bitfield_, remote_peer->bitfield); xbt_assert(not remote_peer->choked_download, "Can't received a piece if I'm choked !"); xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES), "Wrong piece received"); // TODO: Execute a computation. if (hasNotPiece(static_cast<unsigned int>(message->piece))) { updateBitfieldBlocks(message->piece, message->block_index, message->block_length); if (hasCompletedPiece(static_cast<unsigned int>(message->piece))) { // Removing the piece from our piece list removeCurrentPiece(remote_peer, message->piece); // Setting the fact that we have the piece bitfield_ = bitfield_ | (1U << static_cast<unsigned int>(message->piece)); XBT_DEBUG("My status is now %s", getStatus().c_str()); // Sending the information to all the peers we are connected to sendHaveToAllPeers(message->piece); // sending UNINTERESTED to peers that do not have what we want. updateInterestedAfterReceive(); } else { // piece not completed sendRequestTo(remote_peer, message->piece); // ask for the next block } } else { XBT_DEBUG("However, we already have it"); xbt_assert(ENABLE_END_GAME_MODE, "Should not happen because we don't use end game mode !"); requestNewPieceTo(remote_peer); } break; case MESSAGE_CANCEL: break; default: THROW_IMPOSSIBLE; } // Update the peer speed. if (remote_peer) { remote_peer->addSpeedValue(1.0 / (simgrid::s4u::Engine::get_clock() - begin_receive_time)); } begin_receive_time = simgrid::s4u::Engine::get_clock(); }
/*! Send a request to the first receptor in the list. \sa vpNetwork::sendRequestTo() \sa vpNetwork::sendAndEncodeRequest() \sa vpNetwork::sendAndEncodeRequestTo() \sa vpNetwork::send() \sa vpNetwork::sendTo() \param req : Request to send. \return The number of bytes that have been sent, -1 if an error occured. */ int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req,0); }