1 /* <!-- copyright */
2 /*
3  * aria2 - The high speed download utility
4  *
5  * Copyright (C) 2009 Tatsuhiro Tsujikawa
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  * In addition, as a special exception, the copyright holders give
22  * permission to link the code of portions of this program with the
23  * OpenSSL library under certain conditions as described in each
24  * individual source file, and distribute linked combinations
25  * including the two.
26  * You must obey the GNU General Public License in all respects
27  * for all of the code used other than OpenSSL.  If you modify
28  * file(s) with this exception, you may extend this exception to your
29  * version of the file(s), but you are not obligated to do so.  If you
30  * do not wish to do so, delete this exception statement from your
31  * version.  If you delete this exception statement from all source
32  * files in the program, then also delete it here.
33  */
34 /* copyright --> */
35 #include "UTMetadataDataExtensionMessage.h"
36 #include "bencode2.h"
37 #include "util.h"
38 #include "a2functional.h"
39 #include "DownloadContext.h"
40 #include "UTMetadataRequestTracker.h"
41 #include "PieceStorage.h"
42 #include "BtConstants.h"
43 #include "MessageDigest.h"
44 #include "message_digest_helper.h"
45 #include "bittorrent_helper.h"
46 #include "DiskAdaptor.h"
47 #include "Piece.h"
48 #include "Logger.h"
49 #include "LogFactory.h"
50 #include "DlAbortEx.h"
51 #include "fmt.h"
52 
53 namespace aria2 {
54 
UTMetadataDataExtensionMessage(uint8_t extensionMessageID)55 UTMetadataDataExtensionMessage::UTMetadataDataExtensionMessage(
56     uint8_t extensionMessageID)
57     : UTMetadataExtensionMessage{extensionMessageID},
58       totalSize_{0},
59       dctx_{nullptr},
60       pieceStorage_{nullptr},
61       tracker_{nullptr}
62 {
63 }
64 
getPayload()65 std::string UTMetadataDataExtensionMessage::getPayload()
66 {
67   Dict dict;
68   dict.put("msg_type", Integer::g(1));
69   dict.put("piece", Integer::g(getIndex()));
70   dict.put("total_size", Integer::g(totalSize_));
71   return bencode2::encode(&dict) + data_;
72 }
73 
toString() const74 std::string UTMetadataDataExtensionMessage::toString() const
75 {
76   return fmt("ut_metadata data piece=%lu",
77              static_cast<unsigned long>(getIndex()));
78 }
79 
doReceivedAction()80 void UTMetadataDataExtensionMessage::doReceivedAction()
81 {
82   if (tracker_->tracks(getIndex())) {
83     A2_LOG_DEBUG(fmt("ut_metadata index=%lu found in tracking list",
84                      static_cast<unsigned long>(getIndex())));
85     tracker_->remove(getIndex());
86     pieceStorage_->getDiskAdaptor()->writeData(
87         reinterpret_cast<const unsigned char*>(data_.c_str()), data_.size(),
88         getIndex() * METADATA_PIECE_SIZE);
89     pieceStorage_->completePiece(pieceStorage_->getPiece(getIndex()));
90     if (pieceStorage_->downloadFinished()) {
91       std::string metadata = util::toString(pieceStorage_->getDiskAdaptor());
92       unsigned char infoHash[INFO_HASH_LENGTH];
93       message_digest::digest(infoHash, INFO_HASH_LENGTH,
94                              MessageDigest::sha1().get(), metadata.data(),
95                              metadata.size());
96       if (memcmp(infoHash, bittorrent::getInfoHash(dctx_), INFO_HASH_LENGTH) ==
97           0) {
98         A2_LOG_INFO("Got ut_metadata");
99       }
100       else {
101         A2_LOG_INFO("Got wrong ut_metadata");
102         for (size_t i = 0; i < dctx_->getNumPieces(); ++i) {
103           pieceStorage_->markPieceMissing(i);
104         }
105         throw DL_ABORT_EX("Got wrong ut_metadata");
106       }
107     }
108   }
109   else {
110     A2_LOG_DEBUG(fmt("ut_metadata index=%lu is not tracked",
111                      static_cast<unsigned long>(getIndex())));
112   }
113 }
114 
setTotalSize(size_t totalSize)115 void UTMetadataDataExtensionMessage::setTotalSize(size_t totalSize)
116 {
117   totalSize_ = totalSize;
118 }
119 
getTotalSize() const120 size_t UTMetadataDataExtensionMessage::getTotalSize() const
121 {
122   return totalSize_;
123 }
124 
setData(const std::string & data)125 void UTMetadataDataExtensionMessage::setData(const std::string& data)
126 {
127   data_ = data;
128 }
129 
getData() const130 const std::string& UTMetadataDataExtensionMessage::getData() const
131 {
132   return data_;
133 }
134 
setPieceStorage(PieceStorage * pieceStorage)135 void UTMetadataDataExtensionMessage::setPieceStorage(PieceStorage* pieceStorage)
136 {
137   pieceStorage_ = pieceStorage;
138 }
139 
setUTMetadataRequestTracker(UTMetadataRequestTracker * tracker)140 void UTMetadataDataExtensionMessage::setUTMetadataRequestTracker(
141     UTMetadataRequestTracker* tracker)
142 {
143   tracker_ = tracker;
144 }
145 
setDownloadContext(DownloadContext * dctx)146 void UTMetadataDataExtensionMessage::setDownloadContext(DownloadContext* dctx)
147 {
148   dctx_ = dctx;
149 }
150 
151 } // namespace aria2
152