2 #ifndef EL__PROTOCOL_BITTORRENT_COMMON_H
3 #define EL__PROTOCOL_BITTORRENT_COMMON_H
5 #include "main/timer.h"
6 #include "network/progress.h"
7 #include "network/socket.h"
8 #include "network/state.h"
9 #include "protocol/protocol.h"
10 #include "protocol/uri.h"
11 #include "util/error.h"
12 #include "util/lists.h"
14 #include "util/sha1.h"
15 #include "util/time.h"
18 struct bittorrent_fetcher
;
22 /** The least acceptable default sharing rate. */
23 #define BITTORRENT_DEFAULT_SHARING_RATE 0.250
25 /** The number of seconds between updating the connection state and most
26 * importantly choke and unchoke peer connections. */
27 #define BITTORRENT_DEFAULT_CHOKE_INTERVAL 10
29 /** The length regarded as ``typical'' by the community wiki specification.
30 * Looks like Bram uses 2^14 here.
31 * Used for the protocol.bittorrent.request_length option */
32 #define BITTORRENT_REQUEST_LENGTH (1 << 14)
34 /** The length of requested blocks of pieces should not exceed 2^17 bytes.
35 * Used for the protocol.bittorrent.max_request_length option.
36 * Bram uses 2^23 here. */
37 #define BITTORRENT_REQUEST_ACCEPT_LENGTH (1 << 23)
39 /** The maximum size to allow a peer message to have. */
40 /* Bram uses 2^23 here. */
41 #define BITTORRENT_MESSAGE_MAX_SIZE (1 << 23)
44 /** 20-byte string ID used for both peer IDs and info-hashes. */
45 typedef sha1_digest_bin_T bittorrent_id_T
;
47 /** Special peer ID used for determining whether an ID has been set. */
48 extern const bittorrent_id_T BITTORRENT_NULL_ID
;
50 /** Check if the ID has been set. */
51 #define bittorrent_id_is_empty(id) \
52 (!memcmp(id, BITTORRENT_NULL_ID, sizeof(bittorrent_id_T)))
55 /** BitTorrent error states. */
56 enum bittorrent_state
{
57 BITTORRENT_STATE_OK
, /**< All is well. */
58 BITTORRENT_STATE_ERROR
, /**< Some error happened. */
59 BITTORRENT_STATE_REQUEST_FAILURE
, /**< Failure from tracker. */
60 BITTORRENT_STATE_OUT_OF_MEM
, /**< Allocation failure. */
61 BITTORRENT_STATE_CACHE_FAILURE
, /**< Cache data access failed. */
62 BITTORRENT_STATE_CACHE_RESUME
, /**< Resume state from disk. */
63 BITTORRENT_STATE_FILE_MISSING
, /**< File does not exist. */
66 /** For showing tracker failure responses to the user. */
67 struct bittorrent_message
{
68 LIST_HEAD(struct bittorrent_message
);
71 struct connection_state state
;
72 unsigned char string
[1];
76 /* ************************************************************************** */
77 /* Peer-wire types: */
78 /* ************************************************************************** */
80 /** BitTorrent peer-wire state and message IDs. */
81 enum bittorrent_message_id
{
82 /* Special internal state and message type. */
83 BITTORRENT_MESSAGE_ERROR
= -3,
84 BITTORRENT_MESSAGE_INCOMPLETE
= -2,
85 BITTORRENT_MESSAGE_KEEP_ALIVE
= -1,
87 /* Valid message types. */
88 BITTORRENT_MESSAGE_CHOKE
= 0,
89 BITTORRENT_MESSAGE_UNCHOKE
= 1,
90 BITTORRENT_MESSAGE_INTERESTED
= 2,
91 BITTORRENT_MESSAGE_NOT_INTERESTED
= 3,
92 BITTORRENT_MESSAGE_HAVE
= 4,
93 BITTORRENT_MESSAGE_BITFIELD
= 5,
94 BITTORRENT_MESSAGE_REQUEST
= 6,
95 BITTORRENT_MESSAGE_PIECE
= 7,
96 BITTORRENT_MESSAGE_CANCEL
= 8,
99 /** The peer request matches information sent in the request and cancel messages
100 * in the peer-wire protocol. See the piece cache header file (cache.h) for more
101 * information about the cloned flag. */
102 struct bittorrent_peer_request
{
103 LIST_HEAD(struct bittorrent_peer_request
);
105 uint32_t piece
; /**< Zero-based piece index. */
106 uint32_t offset
; /**< Zero-based piece byte offset. */
107 uint32_t length
; /**< The wanted number of bytes. */
109 uint16_t block
; /**< The block index in the piece. */
111 enum bittorrent_message_id id
; /**< ID of queued pending message. */
113 unsigned int cloned
:1; /**< The request was cloned. */
114 unsigned int requested
:1; /**< Whether it has been requested. */
117 struct bittorrent_peer_status
{
118 /** FIFO-like recording of requests. */
119 LIST_OF(struct bittorrent_peer_request
) requests
;
121 /* Flags for scheduling updating of the peer state. */
122 unsigned int choked
:1; /**< The peer was choked. */
123 unsigned int interested
:1; /**< The peer is interested. */
124 unsigned int snubbed
:1; /**< The peer was snubbed. */
126 /* State flags used for determining what to accept. */
127 unsigned int handshake
:1; /**< The handshake was sent. */
128 unsigned int bitfield
:1; /**< The bitfield was sent. */
129 unsigned int initiater
:1; /**< Initiater of the connection. */
130 unsigned int seeder
:1; /**< The peer has the complete torrent. */
133 struct bittorrent_peer_stats
{
137 double download_rate
;
144 /** Peer connection information. */
145 struct bittorrent_peer_connection
{
146 LIST_HEAD(struct bittorrent_peer_connection
);
148 /** Unique peer ID string which can be used to look-up the peer hash. */
151 /** Timer handle for scheduling timeouts. */
154 /** Socket information. */
155 struct socket
*socket
;
157 /** Progress information and counter for the number of uploaded or
158 * downloaded bytes depending on the mode. */
159 struct bittorrent_peer_stats stats
;
161 /** The BitTorrent connection the peer connection is associated with.
162 * For recently accepted peer connections it might be NULL indicating
163 * that the info_hash has not yet been read from the handshake. */
164 struct bittorrent_connection
*bittorrent
;
166 /** Local client and remote peer status info. */
167 struct bittorrent_peer_status local
;
168 struct bittorrent_peer_status remote
;
170 /** Outgoing message queue. Note piece messages are maintained entirely
171 * in the request list in the bittorrent_peer_status struct. */
172 LIST_OF(struct bittorrent_peer_request
) queue
;
174 /** A bitfield of the available pieces from the peer.
175 * The size depends on the number of pieces. */
176 struct bitfield
*bitfield
;
180 /* ************************************************************************** */
182 /* ************************************************************************** */
184 /** Event state information needed by the tracker. */
185 enum bittorrent_tracker_event
{
186 BITTORRENT_EVENT_STARTED
= 0, /**< XXX: Zero, to always send first */
187 BITTORRENT_EVENT_STOPPED
, /**< Graceful shut down */
188 BITTORRENT_EVENT_COMPLETED
, /**< Download was completed */
189 BITTORRENT_EVENT_REGULAR
, /**< Regular (periodical) tracker request */
192 /** This stores info about tracker requests.
193 * It is not a real connection because it consists of a series of HTTP requests
194 * but both the tracker and client is supposed to keep state information across
196 struct bittorrent_tracker_connection
{
197 /** Used for keeping track of when to send event info to the tracker. */
198 enum bittorrent_tracker_event event
;
200 /** Time in seconds between contacting the tracker and a timer handle. */
204 /** Requesting the tracker failed or was never started so no
205 * event=stopped should be sent. */
206 unsigned int failed
:1;
207 unsigned int started
:1;
211 /* ************************************************************************** */
212 /* Metafile types: */
213 /* ************************************************************************** */
215 /** Information about peers returned by the tracker. */
216 struct bittorrent_peer
{
217 LIST_HEAD(struct bittorrent_peer
);
219 bittorrent_id_T id
; /**< Unique peer ID string. */
220 uint16_t port
; /**< The port number to connect to. */
221 unsigned char ip
[1]; /**< String with a IPv4 or IPv6 address. */
224 /** Information about a file in the torrent. */
225 struct bittorrent_file
{
226 LIST_HEAD(struct bittorrent_file
);
228 off_t length
; /**< Length of the file in bytes. */
229 md5_digest_hex_T md5sum
; /**< Hexadecimal MD5 sum of the file. */
231 unsigned char name
[1]; /**< Filename converted from path list. */
234 /** Static information from the .torrent metafile. */
235 struct bittorrent_meta
{
236 /** The SHA1 info hash of the value of the info key from the metainfo
237 * .torrent file is used regularly when connecting to both the tracker
239 bittorrent_id_T info_hash
;
241 /** Optional information about the creation time of the torrent.
242 * Used if the document.download.set_original_time is true. */
243 time_t creation_date
;
245 /** Optional comment in free-form text. */
246 unsigned char *comment
;
248 /** The announced URI of each available tracker. */
249 struct uri_list tracker_uris
;
251 /** The number of pieces. */
254 /** The number of bytes in each piece. */
255 uint32_t piece_length
;
256 /** The last piece can be shorter than the others. */
257 uint32_t last_piece_length
;
259 /** List of concatenated SHA1 hash values for each piece. */
260 unsigned char *piece_hash
;
262 /** The type of the torrent. */
263 enum { BITTORRENT_SINGLE_FILE
, BITTORRENT_MULTI_FILE
} type
;
265 /** Potential bad file path detected. */
266 unsigned int malicious_paths
:1;
268 /** The name of either the single file or the top-most directory. */
271 /** A list with information about files in the torrent.
272 * The list is a singleton for single-file torrents. */
273 LIST_OF(struct bittorrent_file
) files
;
276 enum bittorrent_connection_mode
{
277 BITTORRENT_MODE_PIECELESS
, /**< The client has no piece to share. */
278 BITTORRENT_MODE_NORMAL
, /**< The client is up- and downloading. */
279 BITTORRENT_MODE_END_GAME
, /**< All remaining pieces are requested. */
280 BITTORRENT_MODE_SEEDER
, /**< The client is only uploading. */
283 /** This stores info about an active BitTorrent connection. Note, the list head
284 * is used by the handling of the peer-wire listening socket and should only be
285 * managed by that. */
286 struct bittorrent_connection
{
287 LIST_HEAD(struct bittorrent_connection
);
289 enum bittorrent_connection_mode mode
;
291 /** Static information from the .torrent metafile. */
292 struct bittorrent_meta meta
;
294 /** Dynamic tracker information. */
295 struct bittorrent_tracker_connection tracker
;
297 /** Dynamic tracker information. */
298 struct bittorrent_piece_cache
*cache
;
300 /** Back-reference to the connection the bittorrent connection belongs
302 struct connection
*conn
;
305 * The size is controlled by the protocol.bittorrent.max_active_peers
307 LIST_OF(struct bittorrent_peer_connection
) peers
;
309 /** List of information about potential peers.
310 * @todo TODO: Use hash. */
311 LIST_OF(struct bittorrent_peer
) peer_pool
;
313 /** The peer ID of the client. */
314 bittorrent_id_T peer_id
;
316 /** The port of the listening socket */
319 /** Timer handle for scheduling periodic updating and rating of peer
323 /** Statistics for the tracker and total progress information for the
325 struct progress upload_progress
;
330 /** Number of seeders. */
332 /** Number of leechers. */
337 /** Information about any running metainfo file or tracker request. */
338 struct bittorrent_fetcher
*fetch
;
340 /** For notifying on completion.
342 struct terminal
*term
;
345 /** Like struct string, except the data is const and not freed via
346 * this structure. So it is okay to make @c source point to data that
347 * is part of a larger buffer. Also, there is no @c magic member here. */
348 struct bittorrent_const_string
{
349 const unsigned char *source
;
353 static inline uint32_t
354 get_bittorrent_piece_length(struct bittorrent_meta
*meta
, uint32_t piece
)
356 return piece
== meta
->pieces
- 1
357 ? meta
->last_piece_length
: meta
->piece_length
;
360 unsigned char *get_hexed_bittorrent_id(bittorrent_id_T id
);
364 bittorrent_piece_is_valid(struct bittorrent_meta
*meta
,
365 uint32_t piece
, unsigned char *data
, uint32_t datalen
);
367 void init_bittorrent_peer_id(bittorrent_id_T peer_id
);
370 bittorrent_id_is_known(struct bittorrent_connection
*bittorrent
,
373 enum bittorrent_state
374 add_peer_to_bittorrent_pool(struct bittorrent_connection
*bittorrent
,
375 bittorrent_id_T id
, int port
,
376 const unsigned char *ip
, int iplen
);
378 struct bittorrent_peer
*
379 get_peer_from_bittorrent_pool(struct bittorrent_connection
*bittorrent
,
382 void done_bittorrent_meta(struct bittorrent_meta
*meta
);
383 void done_bittorrent_message(struct bittorrent_message
*message
);
386 /* ************************************************************************** */
387 /* Debug 'pretty printing' functions: */
388 /* ************************************************************************** */
390 unsigned char *get_peer_id(bittorrent_id_T peer
);
391 unsigned char *get_peer_message(enum bittorrent_message_id message_id
);
393 /* ************************************************************************** */
394 /* Peer request management: */
395 /* ************************************************************************** */
397 struct bittorrent_peer_request
*
398 get_bittorrent_peer_request(struct bittorrent_peer_status
*status
,
399 uint32_t piece
, uint32_t offset
, uint32_t length
);
402 add_bittorrent_peer_request(struct bittorrent_peer_status
*status
,
403 uint32_t piece
, uint32_t offset
, uint32_t length
);
406 del_bittorrent_peer_request(struct bittorrent_peer_status
*status
,
407 uint32_t piece
, uint32_t offset
, uint32_t length
);
410 /* ************************************************************************** */
412 /* ************************************************************************** */
414 typedef void (*bittorrent_fetch_callback_T
)(void *, struct connection_state
,
415 struct bittorrent_const_string
*);
417 struct bittorrent_fetcher
*
418 init_bittorrent_fetch(struct bittorrent_fetcher
**fetcher_ref
,
419 struct uri
*uri
, bittorrent_fetch_callback_T callback
,
420 void *data
, int delete);
421 void done_bittorrent_fetch(struct bittorrent_fetcher
**fetcher_ref
);
424 /* ************************************************************************** */
426 /* ************************************************************************** */
428 enum bittorrent_blacklist_flags
{
429 BITTORRENT_BLACKLIST_NONE
, /**< No blacklisting is in effect */
430 BITTORRENT_BLACKLIST_PEER_POOL
, /**< Blacklist from peer pool. */
431 BITTORRENT_BLACKLIST_MALICIOUS
, /**< Malicious peer, refuse connection */
432 BITTORRENT_BLACKLIST_BEHAVIOUR
, /**< Unfair behaviour, refuse connection */
436 add_bittorrent_blacklist_flags(bittorrent_id_T peer_id
,
437 enum bittorrent_blacklist_flags flags
);
440 del_bittorrent_blacklist_flags(bittorrent_id_T peer_id
,
441 enum bittorrent_blacklist_flags flags
);
443 enum bittorrent_blacklist_flags
444 get_bittorrent_blacklist_flags(bittorrent_id_T peer_id
);
446 void done_bittorrent_blacklist(void);