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"));
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
/* This is basically the choke period handler. */
88
update_bittorrent_connection_state(struct connection *conn)
90
struct bittorrent_connection *bittorrent = conn->info;
91
struct bittorrent_peer_connection *peer, *next_peer;
92
int peer_conns, max_peer_conns;
93
int min_uploads = get_opt_int("protocol.bittorrent.min_uploads");
94
int max_uploads = get_opt_int("protocol.bittorrent.max_uploads");
96
set_bittorrent_connection_timer(conn);
97
set_connection_timeout(conn);
99
peer_conns = list_size(&bittorrent->peers);
100
max_peer_conns = get_opt_int("protocol.bittorrent.peerwire.connections");
102
/* First ``age'' the peer rates _before_ the sorting. */
103
foreach (peer, bittorrent->peers)
104
update_bittorrent_peer_connection_stats(peer, 0, 0, 0);
106
/* Sort the peers so that the best peers are at the list start. */
107
sort_bittorrent_peer_connections(bittorrent);
109
/* Unchoke all the optimal peers. In good spirit, also unchoke all
110
* uninterested peers until the maximum number of interested peers have
111
* been unchoked. The rest is choked. */
112
foreachsafe (peer, next_peer, bittorrent->peers) {
113
if (!peer->remote.handshake)
116
if (min_uploads < max_uploads) {
117
if (peer->remote.choked)
118
unchoke_bittorrent_peer(peer);
120
peer->remote.choked = 0;
122
/* Uninterested peers are not counted as uploads. */
123
if (peer->remote.interested)
127
if (!peer->remote.choked)
128
choke_bittorrent_peer(peer);
130
peer->remote.choked = 1;
133
/* Can remove the peer so we use foreachsafe(). */
134
update_bittorrent_peer_connection_state(peer);
137
/* FIXME: Find peer(s) to optimistically unchoke. */
139
update_bittorrent_piece_cache_state(bittorrent);
141
/* Close or open peers connections. */
142
if (peer_conns > max_peer_conns) {
143
struct bittorrent_peer_connection *prev;
145
foreachsafe (peer, prev, bittorrent->peers) {
146
done_bittorrent_peer_connection(peer);
147
if (--peer_conns <= max_peer_conns)
151
} else if (peer_conns < max_peer_conns) {
152
struct bittorrent_peer *peer_info, *next_peer_info;
154
foreachsafe (peer_info, next_peer_info, bittorrent->peer_pool) {
155
enum bittorrent_state state;
157
state = make_bittorrent_peer_connection(bittorrent, peer_info);
158
if (state != BITTORRENT_STATE_OK)
161
del_from_list(peer_info);
163
if (++peer_conns >= max_peer_conns)
168
assert(peer_conns <= max_peer_conns);
170
/* Shrink the peer pool. */
171
if (!list_empty(bittorrent->peers)) {
172
struct bittorrent_peer *peer_info, *next_peer_info;
173
int pool_size = get_opt_int("protocol.bittorrent.peerwire.pool_size");
176
foreachsafe (peer_info, next_peer_info, bittorrent->peer_pool) {
178
if (!pool_size) break;
180
if (pool_peers < pool_size) {
185
del_from_list(peer_info);
192
update_bittorrent_connection_upload(void *data)
194
struct bittorrent_connection *bittorrent = data;
196
update_progress(&bittorrent->upload_progress,
197
bittorrent->uploaded,
198
bittorrent->downloaded,
199
bittorrent->uploaded);
204
update_bittorrent_connection_stats(struct bittorrent_connection *bittorrent,
205
off_t downloaded, off_t uploaded,
208
struct bittorrent_meta *meta = &bittorrent->meta;
210
if (bittorrent->conn->est_length == -1) {
211
off_t length = (off_t) (meta->pieces - 1) * meta->piece_length
212
+ meta->last_piece_length;
214
bittorrent->conn->est_length = length;
215
bittorrent->left = length;
216
start_update_progress(&bittorrent->upload_progress,
217
update_bittorrent_connection_upload,
221
if (bittorrent->upload_progress.timer == TIMER_ID_UNDEF
222
&& bittorrent->uploaded)
223
update_bittorrent_connection_upload(bittorrent);
225
bittorrent->conn->received += received;
226
bittorrent->conn->from += downloaded;
228
bittorrent->downloaded += downloaded;
229
bittorrent->uploaded += uploaded;
230
bittorrent->left -= downloaded;
232
if (!bittorrent->downloaded) return;
234
bittorrent->sharing_rate = (double) bittorrent->uploaded
235
/ bittorrent->downloaded;
239
/* ************************************************************************** */
240
/* The ``main'' BitTorrent connection setup: */
241
/* ************************************************************************** */
243
/* Callback which is attached to the ELinks connection and invoked when the
244
* connection is shutdown. */
246
done_bittorrent_connection(struct connection *conn)
248
struct bittorrent_connection *bittorrent = conn->info;
249
struct bittorrent_peer_connection *peer, *next;
253
/* We don't want the tracker to see the fetch. */
254
if (bittorrent->fetch)
255
done_bittorrent_fetch(&bittorrent->fetch);
257
foreachsafe (peer, next, bittorrent->peers)
258
done_bittorrent_peer_connection(peer);
260
done_bittorrent_tracker_connection(conn);
261
done_bittorrent_listening_socket(conn);
262
if (bittorrent->cache)
263
done_bittorrent_piece_cache(bittorrent);
264
done_bittorrent_meta(&bittorrent->meta);
266
kill_timer(&bittorrent->timer);
267
kill_timer(&bittorrent->upload_progress.timer);
269
free_list(bittorrent->peer_pool);
271
mem_free_set(&conn->info, NULL);
274
static struct bittorrent_connection *
275
init_bittorrent_connection(struct connection *conn)
277
struct bittorrent_connection *bittorrent;
279
bittorrent = mem_calloc(1, sizeof(*bittorrent));
280
if (!bittorrent) return NULL;
282
init_list(bittorrent->peers);
283
init_list(bittorrent->peer_pool);
285
conn->info = bittorrent;
286
conn->done = done_bittorrent_connection;
288
init_bittorrent_peer_id(bittorrent->peer_id);
290
bittorrent->conn = conn;
291
bittorrent->tracker.timer = TIMER_ID_UNDEF;
297
bittorrent_resume_callback(struct bittorrent_connection *bittorrent)
299
enum connection_state state;
301
/* Failing to create the listening socket is fatal. */
302
state = init_bittorrent_listening_socket(bittorrent->conn);
304
retry_connection(bittorrent->conn, state);
308
set_connection_state(bittorrent->conn, S_CONN_TRACKER);
309
send_bittorrent_tracker_request(bittorrent->conn);
312
/* Metainfo file download callback */
314
bittorrent_metainfo_callback(void *data, enum connection_state state,
315
struct string *response)
317
struct connection *conn = data;
318
struct bittorrent_connection *bittorrent = conn->info;
320
bittorrent->fetch = NULL;
323
abort_connection(conn, state);
327
switch (parse_bittorrent_metafile(&bittorrent->meta, response)) {
328
case BITTORRENT_STATE_OK:
330
size_t size = list_size(&bittorrent->meta.files);
333
assert(bittorrent->tracker.event == BITTORRENT_EVENT_STARTED);
335
selection = get_bittorrent_selection(conn->uri, size);
337
struct bittorrent_file *file;
340
foreach (file, bittorrent->meta.files)
341
file->selected = selection[index++];
346
switch (init_bittorrent_piece_cache(bittorrent, response)) {
347
case BITTORRENT_STATE_OK:
348
bittorrent_resume_callback(bittorrent);
351
case BITTORRENT_STATE_CACHE_RESUME:
352
set_connection_state(bittorrent->conn, S_RESUME);
355
case BITTORRENT_STATE_OUT_OF_MEM:
356
state = S_OUT_OF_MEM;
360
state = S_BITTORRENT_ERROR;
365
case BITTORRENT_STATE_OUT_OF_MEM:
366
state = S_OUT_OF_MEM;
369
case BITTORRENT_STATE_ERROR:
371
/* XXX: This can also happen when passing bittorrent:<uri> and
372
* <uri> gives an HTTP 404 response. It might be worth fixing by
373
* looking at the protocol header, however, direct usage of the
374
* internal bittorrent: is at your own risk ... at least for
376
state = S_BITTORRENT_METAINFO;
379
abort_connection(conn, state);
382
/* The entry point for BitTorrent downloads. */
384
bittorrent_protocol_handler(struct connection *conn)
387
struct bittorrent_connection *bittorrent;
389
bittorrent = init_bittorrent_connection(conn);
391
abort_connection(conn, S_OUT_OF_MEM);
395
assert(conn->uri->datalen);
397
uri = get_uri(conn->uri->data, 0);
399
abort_connection(conn, S_OUT_OF_MEM);
403
set_connection_state(conn, S_CONN);
404
set_connection_timeout(conn);
407
init_bittorrent_fetch(&bittorrent->fetch, uri,
408
bittorrent_metainfo_callback, conn, 0);