keker123

peer_connect.cpp

May 5th, 2023
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.59 KB | None | 0 0
  1. #include "byte_tools.h"
  2. #include "peer_connect.h"
  3. #include "message.h"
  4. #include <iostream>
  5. #include <sstream>
  6. #include <utility>
  7. #include <cassert>
  8.  
  9. using namespace std::chrono_literals;
  10.  
  11. PeerPiecesAvailability::PeerPiecesAvailability() {}
  12.  
  13. PeerPiecesAvailability::PeerPiecesAvailability(std::string bitfield) : bitfield_(std::move(bitfield)) {}
  14.  
  15. bool PeerPiecesAvailability::IsPieceAvailable(size_t pieceIndex) const {
  16.     return bitfield_[pieceIndex / 8] & (1 << (7 - pieceIndex % 8));
  17. }
  18.  
  19. void PeerPiecesAvailability::SetPieceAvailability(size_t pieceIndex) {
  20.     bitfield_[pieceIndex / 8] |= (1 << (7 - pieceIndex % 8));
  21. }
  22.  
  23. size_t PeerPiecesAvailability::Size() const {
  24.     return bitfield_.size() * 8;
  25. }
  26.  
  27. PeerConnect::PeerConnect(const Peer &peer, const TorrentFile &tf, std::string selfPeerId) :
  28.         tf_(tf),
  29.         socket_(peer.ip, peer.port, 500ms, 500ms),
  30.         selfPeerId_(std::move(selfPeerId)),
  31.         terminated_(false),
  32.         choked_(true) {}
  33.  
  34. void PeerConnect::Run() {
  35.     while (!terminated_) {
  36.         if (EstablishConnection()) {
  37.             std::cout << "Connection established to peer" << std::endl;
  38.             MainLoop();
  39.         } else {
  40.             std::cerr << "Cannot establish connection to peer" << std::endl;
  41.             Terminate();
  42.         }
  43.     }
  44. }
  45.  
  46. void PeerConnect::PerformHandshake() {
  47.     this->socket_.EstablishConnection();
  48.  
  49.     std::string handshake = "BitTorrent protocol00000000" + this->tf_.infoHash +
  50.                             this->selfPeerId_;
  51.     handshake = ((char) 19) + handshake;
  52.  
  53.     this->socket_.SendData(handshake);
  54.  
  55.     std::string response = this->socket_.ReceiveData(68);
  56.     if (response[0] != '\x13' || response.substr(1, 19) != "BitTorrent protocol") {
  57.         throw std::runtime_error("Handshake failed");
  58.     }
  59.     if (response.substr(28, 20) != this->tf_.infoHash) {
  60.         throw std::runtime_error("Peer infohash another");
  61.     }
  62.  
  63. }
  64.  
  65. bool PeerConnect::EstablishConnection() {
  66.     try {
  67.         PerformHandshake();
  68.         ReceiveBitfield();
  69.         SendInterested();
  70.         return true;
  71.     } catch (const std::exception &e) {
  72.         std::cerr << "Failed to establish connection with peer " << socket_.GetIp() << ":" <<
  73.                   socket_.GetPort() << " -- " << e.what() << std::endl;
  74.         return false;
  75.     }
  76. }
  77.  
  78. void PeerConnect::ReceiveBitfield() {
  79.     std::string response = this->socket_.ReceiveData();
  80.     if ((int) response[0] == 20) {
  81.         response = this->socket_.ReceiveData();
  82.     }
  83.  
  84.     MessageId id = static_cast<MessageId>((int) response[0]);
  85.  
  86.     if (id == MessageId::BitField) {
  87.         std::string bitfield = response.substr(1, response.length() - 1);
  88.         this->piecesAvailability_ = PeerPiecesAvailability(bitfield);
  89.     } else if (id == MessageId::Unchoke) {
  90.         this->choked_ = false;
  91.     } else {
  92.         throw std::runtime_error("Wrong BitField message");
  93.     }
  94. }
  95.  
  96. void PeerConnect::SendInterested() {
  97.     std::string interested = IntToBytes(1) + static_cast<char>(MessageId::Interested);
  98.     this->socket_.SendData(interested);
  99. }
  100.  
  101. void PeerConnect::Terminate() {
  102.     std::cerr << "Terminate" << std::endl;
  103.     terminated_ = true;
  104. }
  105.  
  106. void PeerConnect::MainLoop() {
  107.     /*
  108.      * При проверке вашего решения на сервере этот метод будет переопределен.
  109.      * Если вы провели handshake верно, то в этой функции будет работать обмен данными с пиром
  110.      */
  111.     std::cout << "Dummy main loop" << std::endl;
  112.     Terminate();
  113. }
  114.  
Add Comment
Please, Sign In to add comment