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 }