1 /***************************************************************************
3 * Copyright (C) 2006 David Brodsky *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation and appearing *
8 * in the file LICENSE.GPL included in the packaging of this file. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 * General Public License for more details. *
15 ***************************************************************************/
17 #ifndef _main_storage_h
18 #define _main_storage_h
24 #include <tairon/core/signals.h>
26 #include "core/bencode.h"
47 struct PieceReadersStruct
;
48 struct PieceWritersStruct
;
50 /** \brief Struct for file descriptor and number of references to the file.
58 /** Number of references.
60 unsigned int refCount
;
63 /** \brief Struct containing informations about file's offset and its length.
65 struct FilePositionStruct
71 /** Length of the file.
75 /** Offset of the file from the beginning.
80 /** \brief Struct for informations about piece mapped to the memory.
84 /** \brief Struct for part of the piece that belongs to one file.
86 struct FilePieceStruct
{
87 /** File from which this piece is mapped.
89 const String
*filename
;
91 /** Beginning of the piece in the memory.
95 /** Real beginning of the piece in the memory due to alignment.
99 /** Position of the part in the piece.
103 /** Length of the part.
107 /** Real length of the part.
112 /** Number of references to the piece.
114 unsigned int refCount
;
116 /** List of piece's parts.
118 std::list
<FilePieceStruct
> pieces
;
121 /** \brief Struct for piece's requests.
125 /** Contains indexes of chunks that haven't been requested yet.
127 std::set
<uint32_t> queued
;
129 /** Contains indexes of chunks that have been requested.
131 std::set
<uint32_t> requested
;
134 /** \brief Storage is an abstraction layer over filesystem.
139 /** Constructs a new Storage object and loads fast-resume info (if
142 * \param i Info part of the torrent metainfo;
143 * \param n Node with fast-resume data.
145 Storage(const Tairent::Core::BEncode
&i
, TiXmlNode
*n
= 0);
147 /** Destroys the object.
151 /** Adds a bitfield to the availability list.
153 void addBitField(Tairent::Core::BitField
*b
);
155 /** Tells this storage that everything has been downloaded.
159 /** Returns bitfield of this storage.
161 Tairent::Core::BitField
*getBitField() {
165 /** Returns info part of the torrent metainfo.
167 const Tairent::Core::BEncode
&getMetaInfo() {
171 /** Returns informations about piece.
173 PieceStruct
*getPiece(uint32_t index
);
175 /** Returns number of bytes that are still left to download.
177 uint64_t getRemainingSize();
179 /** Informs this storage that a peer has something new. Returns true if
180 * the piece is interesting for us.
182 * \param index Piece index the peer has.
184 bool gotHave(uint32_t index
);
186 /** Starts downloading of the incoming piece.
188 void gotPiece(uint32_t index
, uint32_t start
, Connection
*c
);
190 /** Sends requested piece to the peer.
192 * \param index Index of the piece.
193 * \param start Start of the chunk within the piece.
194 * \param length Length of the requested chunk.
195 * \param c Connection to the peer.
197 void gotRequest(uint32_t index
, uint32_t start
, uint32_t length
, Connection
*c
);
199 /** Returns true if this storage has stored some piece; otherwise
204 /** Returns true if there is nothing left to be downloaded; otherwise
209 /** Picks a piece to download. If there is a piece to download then
210 * this method returns true; otherwise returns false.
212 * \param b Peer's bitfield.
213 * \param index Index of the block.
214 * \param start Start of the piece within the block.
215 * \param length Length of the piece.
217 bool pickPiece(Tairent::Core::BitField
*b
, uint32_t &index
, uint32_t &start
, uint32_t &length
);
219 /** Informs that a requested piece was downloaded.
221 void pieceDownloaded(uint32_t index
, uint32_t start
);
223 /** Informs that a piece requested by a peer has been sent.
225 void pieceSent(uint32_t index
);
227 /** Removes a bitfield from the availability list.
229 void removeBitField(Tairent::Core::BitField
*b
);
231 /** Informs this storage that we don't expect some pieces to arrive so
232 * it should rerequest them.
234 * \param r Mapping piece index => list of piece parts to rerequest.
236 void reRequest(const std::map
<uint32_t, std::set
<uint32_t> > &r
);
238 /** Returns an XML element that contains informations needed to fast
239 * resume this storage.
241 TiXmlElement
*save();
243 /** Returns true if the client should be interested; otherwise returns
244 * false. (See BitTorrent protocol for details.)
246 bool shouldBeInterested(Tairent::Core::BitField
*b
);
248 /** Unmaps piece that hasn't been read.
250 void unmapPieces(PieceReadersStruct
*readers
);
252 /** Unmaps piece that hasn't been sent.
254 void unmapPieces(PieceWritersStruct
*writers
);
257 /** This signal is emitted when a peer has sent an invalid data.
259 Tairon::Core::Signal1
<void, Connection
*> invalidDataSignal
;
261 /** Emitted when a piece has been successfuly downloaded and its hash
262 * checked against the one from metainfo.
264 Tairon::Core::Signal1
<void, uint32_t> pieceDownloadedSignal
;
267 /** Fills files list and computes total length.
269 void buildFilesList();
271 /** Closes opened file if it isn't used.
273 void closeFile(const String
&name
);
275 /** Creates a file and truncates it to the specified length.
277 void createFile(const String
&name
, uint64_t length
);
279 /** Creates files for this torrent.
283 /** Returns length of a chunk.
285 * \param index Piece number.
286 * \param start Offset of the chunk within the piece.
288 inline uint32_t getChunkLength(uint32_t index
, uint32_t start
);
290 /** Returns length of a piece.
292 * \param index Piece number.
294 inline uint32_t getPieceLength(uint32_t index
);
296 /** Called when a recieved piece's hash is the same as in the info.
298 void hashCorrect(uint32_t index
, HashChecker
*checker
);
300 /** Called when a recieved piece's hash isn't the same as in the info.
302 void hashIncorrect(uint32_t index
, HashChecker
*checker
);
304 /** Converts a path list to a string.
306 String
listToString(const Tairent::Core::BEncode::List
&l
);
308 /** Loads fast resume data from an XML node.
310 void load(TiXmlNode
*n
);
312 /** Loads bitfield from a node.
314 void loadBitField(TiXmlNode
*n
);
316 /** Loads information about queued parts from a node.
318 void loadQueued(TiXmlNode
*n
);
320 /** Maps a piece to the memory.
322 void mapPiece(uint32_t index
);
324 /** Opens a file and returns its descriptor.
326 * \param filename Path with the file including its name.
328 int openFile(const String
&filename
);
330 /** Creates a permutation of pieces numbers.
334 /** Unmaps apiece from the memory. The piece isn't actually unmapped
335 * but moved to the cache from which it will be deleted when it will be
338 void unmapPiece(uint32_t index
);
341 /** How many peers have specific piece.
343 unsigned short *availability
;
345 /** Bitfield of this storage.
347 Tairent::Core::BitField
*bitfield
;
349 /** List of opened files.
351 std::map
<String
, FileStruct
> files
;
353 /** List of positions of files.
355 std::list
<FilePositionStruct
> filesPositions
;
357 /** List of active checkers.
359 std::set
<HashChecker
*> hashCheckers
;
361 /** Info part of the torrent metainfo.
363 const Tairent::Core::BEncode
&info
;
365 /** Number of pieces.
369 /** Length of one piece.
371 uint32_t pieceLength
;
373 /** Mapping from piece index to its struct.
375 std::map
<uint32_t, PieceStruct
*> pieces
;
377 /** List of active requests. The key is a piece index.
379 std::map
<uint32_t, RequestStruct
*> requests
;
381 /** A permutation of length pieceCount.
383 std::list
<uint32_t> scrambled
;
385 /** Sum of lengths of all files.
387 uint64_t totalLength
;
392 }; // namespace Tairent
396 // vim: ai sw=4 ts=4 noet fdm=marker