/* */ #include "BtBitfieldMessage.h" #include #include "bittorrent_helper.h" #include "util.h" #include "DlAbortEx.h" #include "message.h" #include "Peer.h" #include "PieceStorage.h" #include "a2functional.h" namespace aria2 { const char BtBitfieldMessage::NAME[] = "bitfield"; BtBitfieldMessage::BtBitfieldMessage() : SimpleBtMessage(ID, NAME) {} BtBitfieldMessage::BtBitfieldMessage(const unsigned char* bitfield, size_t bitfieldLength) : SimpleBtMessage(ID, NAME), bitfield_(bitfield, bitfield + bitfieldLength) { } BtBitfieldMessage::~BtBitfieldMessage() = default; void BtBitfieldMessage::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) { bitfield_.assign(bitfield, bitfield + bitfieldLength); } std::unique_ptr BtBitfieldMessage::create(const unsigned char* data, size_t dataLength) { bittorrent::assertPayloadLengthGreater(1, dataLength, NAME); bittorrent::assertID(ID, data, NAME); auto message = make_unique(); message->setBitfield(data + 1, dataLength - 1); return message; } void BtBitfieldMessage::doReceivedAction() { if (isMetadataGetMode()) { return; } getPieceStorage()->updatePieceStats(bitfield_.data(), bitfield_.size(), getPeer()->getBitfield()); getPeer()->setBitfield(bitfield_.data(), bitfield_.size()); if (getPeer()->isSeeder() && getPieceStorage()->downloadFinished()) { throw DL_ABORT_EX(MSG_GOOD_BYE_SEEDER); } } std::vector BtBitfieldMessage::createMessage() { /** * len --- 1+bitfieldLength, 4bytes * id --- 5, 1byte * bitfield --- bitfield, bitfieldLength bytes * total: 5+bitfieldLength bytes */ const size_t msgLength = 5 + bitfield_.size(); auto msg = std::vector(msgLength); bittorrent::createPeerMessageString(msg.data(), msgLength, 1 + bitfield_.size(), ID); std::copy(std::begin(bitfield_), std::end(bitfield_), std::begin(msg) + 5); return msg; } std::string BtBitfieldMessage::toString() const { std::string s = NAME; s += ' '; s += util::toHex(bitfield_.data(), bitfield_.size()); return s; } } // namespace aria2