File indexing completed on 2024-06-02 05:05:23

0001 /*
0002     SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "metadatadownload.h"
0008 #include <bcodec/bencoder.h>
0009 #include <peer/utmetadata.h>
0010 #include <util/log.h>
0011 
0012 namespace bt
0013 {
0014 MetadataDownload::MetadataDownload(UTMetaData *ext, Uint32 size)
0015     : ext(ext)
0016     , total_size(size)
0017 {
0018     metadata.resize(size);
0019     Uint32 num_pieces = size / METADATA_PIECE_SIZE;
0020     if (size % METADATA_PIECE_SIZE > 0)
0021         num_pieces++;
0022 
0023     pieces = BitSet(num_pieces);
0024     download(0);
0025 }
0026 
0027 MetadataDownload::~MetadataDownload()
0028 {
0029 }
0030 
0031 void MetadataDownload::reject(Uint32 piece)
0032 {
0033     Out(SYS_GEN | LOG_NOTICE) << "Metadata download, piece " << piece << " rejected" << endl;
0034     downloadNext();
0035 }
0036 
0037 bool MetadataDownload::data(Uint32 piece, const QByteArray &piece_data)
0038 {
0039     // validate data
0040     if (piece >= pieces.getNumBits()) {
0041         Out(SYS_GEN | LOG_NOTICE) << "Metadata download, received piece " << piece << " is invalid " << endl;
0042         downloadNext();
0043         return false;
0044     }
0045 
0046     int size = METADATA_PIECE_SIZE;
0047     if (piece == pieces.getNumBits() - 1 && total_size % METADATA_PIECE_SIZE > 0)
0048         size = total_size % METADATA_PIECE_SIZE;
0049 
0050     if (size != piece_data.size()) {
0051         Out(SYS_GEN | LOG_NOTICE) << "Metadata download, received piece " << piece << " has the wrong size " << endl;
0052         downloadNext();
0053         return false;
0054     }
0055 
0056     // piece fits, so copy into data
0057     // Out(SYS_GEN|LOG_NOTICE) << "Metadata download, dowloaded " << piece << endl;
0058     Uint32 off = piece * METADATA_PIECE_SIZE;
0059     if (static_cast<size_t>(metadata.size()) < off + size) {
0060         Out(SYS_GEN | LOG_NOTICE) << "Metadata download, received large piece " << (off + size) << ", max " << metadata.size() << endl;
0061         metadata.resize(off + size);
0062     }
0063     memcpy(metadata.data() + off, piece_data.data(), size);
0064     pieces.set(piece, true);
0065 
0066     if (!pieces.allOn())
0067         downloadNext();
0068 
0069     return pieces.allOn();
0070 }
0071 
0072 void MetadataDownload::download(Uint32 piece)
0073 {
0074     QByteArray request;
0075     BEncoder enc(new BEncoderBufferOutput(request));
0076     enc.beginDict();
0077     enc.write(QByteArrayLiteral("msg_type"));
0078     enc.write((bt::Uint32)0);
0079     enc.write(QByteArrayLiteral("piece"));
0080     enc.write((bt::Uint32)piece);
0081     enc.end();
0082     ext->sendPacket(request);
0083 }
0084 
0085 void MetadataDownload::downloadNext()
0086 {
0087     Out(SYS_GEN | LOG_NOTICE) << "Metadata download, requesting " << pieces.getNumBits() << " pieces" << endl;
0088     for (Uint32 i = 0; i < pieces.getNumBits(); i++)
0089         if (!pieces.get(i))
0090             download(i);
0091 }
0092 
0093 }