/* */ #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), bitfieldLength_(0) { } BtBitfieldMessage::BtBitfieldMessage(const unsigned char* bitfield, size_t bitfieldLength) : SimpleBtMessage(ID, NAME), bitfieldLength_(0) { setBitfield(bitfield, bitfieldLength); } BtBitfieldMessage::~BtBitfieldMessage() {} void BtBitfieldMessage::setBitfield(const unsigned char* bitfield, size_t bitfieldLength) { if (bitfield_.get() == bitfield) { return; } bitfieldLength_ = bitfieldLength; bitfield_ = make_unique(bitfieldLength_); memcpy(bitfield_.get(), 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_.get(), bitfieldLength_, getPeer()->getBitfield()); getPeer()->setBitfield(bitfield_.get(), bitfieldLength_); 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 + bitfieldLength_; auto msg = std::vector(msgLength); bittorrent::createPeerMessageString(msg.data(), msgLength, 1 + bitfieldLength_, ID); memcpy(msg.data() + 5, bitfield_.get(), bitfieldLength_); return msg; } size_t BtBitfieldMessage::getMessageLength() { return 5 + bitfieldLength_; } std::string BtBitfieldMessage::toString() const { std::string s = NAME; s += " "; s += util::toHex(bitfield_.get(), bitfieldLength_); return s; } } // namespace aria2