1 /* Internal "bittorrent" protocol implementation */
12 #include "cache/cache.h"
13 #include "config/options.h"
14 #include "main/timer.h"
15 #include "network/connection.h"
16 #include "network/progress.h"
17 #include "network/socket.h"
18 #include "protocol/bittorrent/bencoding.h"
19 #include "protocol/bittorrent/bittorrent.h"
20 #include "protocol/bittorrent/common.h"
21 #include "protocol/bittorrent/connection.h"
22 #include "protocol/bittorrent/tracker.h"
23 #include "protocol/bittorrent/peerconnect.h"
24 #include "protocol/bittorrent/peerwire.h"
25 #include "protocol/bittorrent/piececache.h"
26 #include "protocol/protocol.h"
27 #include "protocol/uri.h"
28 #include "session/download.h"
29 #include "util/bitfield.h"
30 #include "util/conv.h"
31 #include "util/memory.h"
32 #include "util/string.h"
33 #include "util/time.h"
36 /* ************************************************************************** */
37 /* Peer selection and connection scheduling: */
38 /* ************************************************************************** */
40 /* Reschedule updating of the connection state. */
42 set_bittorrent_connection_timer(struct connection
*conn
)
44 struct bittorrent_connection
*bittorrent
= conn
->info
;
45 milliseconds_T interval
= sec_to_ms(get_opt_int("protocol.bittorrent.choke_interval", NULL
));
47 install_timer(&bittorrent
->timer
, interval
,
48 (void (*)(void *)) update_bittorrent_connection_state
,
52 /* Sort the peers based on the stats rate, bubbaly style! */
54 sort_bittorrent_peer_connections(struct bittorrent_connection
*bittorrent
)
56 struct bittorrent_peer_connection
*peer
, *prev
;
59 struct bittorrent_peer_connection
*next
;
64 foreachsafe (peer
, next
, bittorrent
->peers
) {
65 if (prev
&& prev
->stats
.download_rate
< peer
->stats
.download_rate
) {
68 add_at_pos(peer
, prev
);
79 foreach (peer
, bittorrent
->peers
) {
80 assert(!prev
|| prev
->stats
.download_rate
>= peer
->stats
.download_rate
);
86 /* Timer callback for @bittorrent->timer. As explained in @install_timer,
87 * this function must erase the expired timer ID from all variables.
89 * This is basically the choke period handler. */
91 update_bittorrent_connection_state(struct connection
*conn
)
93 struct bittorrent_connection
*bittorrent
= conn
->info
;
94 struct bittorrent_peer_connection
*peer
, *next_peer
;
95 int peer_conns
, max_peer_conns
;
96 int min_uploads
= get_opt_int("protocol.bittorrent.min_uploads", NULL
);
97 int max_uploads
= get_opt_int("protocol.bittorrent.max_uploads", NULL
);
99 set_bittorrent_connection_timer(conn
);
100 /* The expired timer ID has now been erased. */
101 set_connection_timeout(conn
);
103 peer_conns
= list_size(&bittorrent
->peers
);
104 max_peer_conns
= get_opt_int("protocol.bittorrent.peerwire.connections", NULL
);
106 /* First ``age'' the peer rates _before_ the sorting. */
107 foreach (peer
, bittorrent
->peers
)
108 update_bittorrent_peer_connection_stats(peer
, 0, 0, 0);
110 /* Sort the peers so that the best peers are at the list start. */
111 sort_bittorrent_peer_connections(bittorrent
);
113 /* Unchoke all the optimal peers. In good spirit, also unchoke all
114 * uninterested peers until the maximum number of interested peers have
115 * been unchoked. The rest is choked. */
116 foreachsafe (peer
, next_peer
, bittorrent
->peers
) {
117 if (!peer
->remote
.handshake
)
120 if (min_uploads
< max_uploads
) {
121 unchoke_bittorrent_peer(peer
);
123 /* Uninterested peers are not counted as uploads. */
124 if (peer
->remote
.interested
)
128 choke_bittorrent_peer(peer
);
131 /* Can remove the peer so we use foreachsafe(). */
132 update_bittorrent_peer_connection_state(peer
);
135 /* FIXME: Find peer(s) to optimistically unchoke. */
137 update_bittorrent_piece_cache_state(bittorrent
);
139 /* Close or open peers connections. */
140 if (peer_conns
> max_peer_conns
) {
141 struct bittorrent_peer_connection
*prev
;
143 foreachsafe (peer
, prev
, bittorrent
->peers
) {
144 done_bittorrent_peer_connection(peer
);
145 if (--peer_conns
<= max_peer_conns
)
149 } else if (peer_conns
< max_peer_conns
) {
150 struct bittorrent_peer
*peer_info
, *next_peer_info
;
152 foreachsafe (peer_info
, next_peer_info
, bittorrent
->peer_pool
) {
153 enum bittorrent_state state
;
155 state
= make_bittorrent_peer_connection(bittorrent
, peer_info
);
156 if (state
!= BITTORRENT_STATE_OK
)
159 del_from_list(peer_info
);
161 if (++peer_conns
>= max_peer_conns
)
166 assert(peer_conns
<= max_peer_conns
);
168 /* Shrink the peer pool. */
169 if (!list_empty(bittorrent
->peers
)) {
170 struct bittorrent_peer
*peer_info
, *next_peer_info
;
171 int pool_size
= get_opt_int("protocol.bittorrent.peerwire.pool_size", NULL
);
174 foreachsafe (peer_info
, next_peer_info
, bittorrent
->peer_pool
) {
176 if (!pool_size
) break;
178 if (pool_peers
< pool_size
) {
183 del_from_list(peer_info
);
189 /* Progress timer callback for @bittorrent->upload_progress. */
191 update_bittorrent_connection_upload(void *data
)
193 struct bittorrent_connection
*bittorrent
= data
;
195 update_progress(&bittorrent
->upload_progress
,
196 bittorrent
->uploaded
,
197 bittorrent
->downloaded
,
198 bittorrent
->uploaded
);
202 update_bittorrent_connection_stats(struct bittorrent_connection
*bittorrent
,
203 off_t downloaded
, off_t uploaded
,
206 struct bittorrent_meta
*meta
= &bittorrent
->meta
;
208 if (bittorrent
->conn
->est_length
== -1) {
209 off_t length
= (off_t
) (meta
->pieces
- 1) * meta
->piece_length
210 + meta
->last_piece_length
;
212 bittorrent
->conn
->est_length
= length
;
213 bittorrent
->left
= length
;
214 start_update_progress(&bittorrent
->upload_progress
,
215 update_bittorrent_connection_upload
,
219 if (bittorrent
->upload_progress
.timer
== TIMER_ID_UNDEF
220 && bittorrent
->uploaded
)
221 update_bittorrent_connection_upload(bittorrent
);
223 bittorrent
->conn
->received
+= received
;
224 bittorrent
->conn
->from
+= downloaded
;
226 bittorrent
->downloaded
+= downloaded
;
227 bittorrent
->uploaded
+= uploaded
;
228 bittorrent
->left
-= downloaded
;
230 if (!bittorrent
->downloaded
) return;
232 bittorrent
->sharing_rate
= (double) bittorrent
->uploaded
233 / bittorrent
->downloaded
;
237 /* ************************************************************************** */
238 /* The ``main'' BitTorrent connection setup: */
239 /* ************************************************************************** */
241 /* Callback which is attached to the ELinks connection and invoked when the
242 * connection is shutdown. */
244 done_bittorrent_connection(struct connection
*conn
)
246 struct bittorrent_connection
*bittorrent
= conn
->info
;
247 struct bittorrent_peer_connection
*peer
, *next
;
250 assert(conn
->done
== done_bittorrent_connection
);
252 /* We don't want the tracker to see the fetch. */
253 if (bittorrent
->fetch
)
254 done_bittorrent_fetch(&bittorrent
->fetch
);
256 foreachsafe (peer
, next
, bittorrent
->peers
)
257 done_bittorrent_peer_connection(peer
);
259 done_bittorrent_tracker_connection(conn
);
260 done_bittorrent_listening_socket(conn
);
261 if (bittorrent
->cache
)
262 done_bittorrent_piece_cache(bittorrent
);
263 done_bittorrent_meta(&bittorrent
->meta
);
265 kill_timer(&bittorrent
->timer
);
266 kill_timer(&bittorrent
->upload_progress
.timer
);
268 free_list(bittorrent
->peer_pool
);
270 mem_free_set(&conn
->info
, NULL
);
274 static struct bittorrent_connection
*
275 init_bittorrent_connection(struct connection
*conn
)
277 struct bittorrent_connection
*bittorrent
;
279 assert(conn
->info
== NULL
);
280 assert(conn
->done
== NULL
);
281 if_assert_failed
return NULL
;
283 bittorrent
= mem_calloc(1, sizeof(*bittorrent
));
284 if (!bittorrent
) return NULL
;
286 init_list(bittorrent
->peers
);
287 init_list(bittorrent
->peer_pool
);
289 /* conn->info and conn->done were asserted as NULL above. */
290 conn
->info
= bittorrent
;
291 conn
->done
= done_bittorrent_connection
;
293 init_bittorrent_peer_id(bittorrent
->peer_id
);
295 bittorrent
->conn
= conn
;
296 bittorrent
->tracker
.timer
= TIMER_ID_UNDEF
;
298 /* Initialize here so that error handling can safely call
299 * free_list on it. */
300 init_list(bittorrent
->meta
.files
);
306 bittorrent_resume_callback(struct bittorrent_connection
*bittorrent
)
308 struct connection_state state
;
310 /* Failing to create the listening socket is fatal. */
311 state
= init_bittorrent_listening_socket(bittorrent
->conn
);
312 if (!is_in_state(state
, S_OK
)) {
313 retry_connection(bittorrent
->conn
, state
);
317 set_connection_state(bittorrent
->conn
, connection_state(S_CONN_TRACKER
));
318 send_bittorrent_tracker_request(bittorrent
->conn
);
321 /* Metainfo file download callback */
323 bittorrent_metainfo_callback(void *data
, struct connection_state state
,
324 struct bittorrent_const_string
*response
)
326 struct connection
*conn
= data
;
327 struct bittorrent_connection
*bittorrent
= conn
->info
;
329 bittorrent
->fetch
= NULL
;
331 if (!is_in_state(state
, S_OK
)) {
332 abort_connection(conn
, state
);
336 switch (parse_bittorrent_metafile(&bittorrent
->meta
, response
)) {
337 case BITTORRENT_STATE_OK
:
339 size_t size
= list_size(&bittorrent
->meta
.files
);
342 assert(bittorrent
->tracker
.event
== BITTORRENT_EVENT_STARTED
);
344 selection
= get_bittorrent_selection(conn
->uri
, size
);
346 struct bittorrent_file
*file
;
349 foreach (file
, bittorrent
->meta
.files
)
350 file
->selected
= selection
[index
++];
355 switch (init_bittorrent_piece_cache(bittorrent
, response
)) {
356 case BITTORRENT_STATE_OK
:
357 bittorrent_resume_callback(bittorrent
);
360 case BITTORRENT_STATE_CACHE_RESUME
:
361 set_connection_state(bittorrent
->conn
,
362 connection_state(S_RESUME
));
365 case BITTORRENT_STATE_OUT_OF_MEM
:
366 state
= connection_state(S_OUT_OF_MEM
);
370 state
= connection_state(S_BITTORRENT_ERROR
);
375 case BITTORRENT_STATE_OUT_OF_MEM
:
376 state
= connection_state(S_OUT_OF_MEM
);
379 case BITTORRENT_STATE_ERROR
:
381 /* XXX: This can also happen when passing bittorrent:<uri> and
382 * <uri> gives an HTTP 404 response. It might be worth fixing by
383 * looking at the protocol header, however, direct usage of the
384 * internal bittorrent: is at your own risk ... at least for
386 state
= connection_state(S_BITTORRENT_METAINFO
);
389 abort_connection(conn
, state
);
392 /* The entry point for BitTorrent downloads. */
394 bittorrent_protocol_handler(struct connection
*conn
)
396 struct uri
*uri
= NULL
;
397 struct bittorrent_connection
*bittorrent
;
399 bittorrent
= init_bittorrent_connection(conn
);
401 abort_connection(conn
, connection_state(S_OUT_OF_MEM
));
405 if (conn
->uri
->datalen
)
406 uri
= get_uri(conn
->uri
->data
, 0);
409 abort_connection(conn
, connection_state(S_BITTORRENT_BAD_URL
));
413 set_connection_state(conn
, connection_state(S_CONN
));
414 set_connection_timeout(conn
);
417 init_bittorrent_fetch(&bittorrent
->fetch
, uri
,
418 bittorrent_metainfo_callback
, conn
, 0);
423 bittorrent_peer_protocol_handler(struct connection
*conn
)
425 abort_connection(conn
, connection_state(S_BITTORRENT_PEER_URL
));