Parcourir la source

o Make the torrent sub struct exist for whole life time of the torrent.

o Better code for stopping the tracker. No more need for the http_redo hack.
master
Richard Nyberg il y a 18 ans
Parent
révision
926838a009
7 fichiers modifiés avec 132 ajouts et 69 suppressions
  1. +25
    -15
      btpd/content.c
  2. +5
    -1
      btpd/content.h
  3. +20
    -5
      btpd/net.c
  4. +6
    -2
      btpd/net.h
  5. +23
    -17
      btpd/torrent.c
  6. +49
    -27
      btpd/tracker_req.c
  7. +4
    -2
      btpd/tracker_req.h

+ 25
- 15
btpd/content.c Voir le fichier

@@ -159,7 +159,7 @@ add_todo(struct content *cm, struct cm_op *op)
}

void
cm_destroy(struct torrent *tp)
cm_kill(struct torrent *tp)
{
struct content *cm = tp->cm;
bts_close(cm->rds);
@@ -168,7 +168,6 @@ cm_destroy(struct torrent *tp)
free(cm->hold_field);
free(cm->pos_field);
tp->cm = NULL;
torrent_on_cm_stopped(tp);
}

void
@@ -215,7 +214,14 @@ cm_stop(struct torrent *tp)
cm_write_done(tp);

if (BTPDQ_EMPTY(&cm->todoq))
cm_destroy(tp);
torrent_on_cm_stopped(tp);
}

int
cm_active(struct torrent *tp)
{
struct content *cm = tp->cm;
return cm->active || !BTPDQ_EMPTY(&cm->todoq);
}

#define SAVE_INTERVAL (& (struct timeval) { 15, 0 })
@@ -261,14 +267,14 @@ cm_td_cb(void *arg)
assert(cm->npieces_got < tp->meta.npieces);
cm->npieces_got++;
set_bit(cm->piece_field, op->u.test.piece);
if (tp->net != NULL)
if (net_active(tp))
dl_on_ok_piece(op->tp->net, op->u.test.piece);
if (cm_full(tp))
cm_write_done(tp);
} else {
cm->ncontent_bytes -= torrent_piece_size(tp, op->u.test.piece);
bzero(cm->block_field + op->u.test.piece * cm->bppbf, cm->bppbf);
if (tp->net != NULL)
if (net_active(tp))
dl_on_bad_piece(tp->net, op->u.test.piece);
}
break;
@@ -281,16 +287,14 @@ cm_td_cb(void *arg)
if (!BTPDQ_EMPTY(&cm->todoq))
run_todo(cm);
else if (!cm->active)
cm_destroy(tp);
torrent_on_cm_stopped(tp);
}

int
cm_start(struct torrent *tp)
void
cm_create(struct torrent *tp)
{
int err;
struct content *cm = btpd_calloc(1, sizeof(*cm));
size_t pfield_size = ceil(tp->meta.npieces / 8.0);
cm->active = 1;
struct content *cm = btpd_calloc(1, sizeof(*cm));
cm->bppbf = ceil((double)tp->meta.piece_length / (1 << 17));
cm->piece_field = btpd_calloc(pfield_size, 1);
cm->hold_field = btpd_calloc(pfield_size, 1);
@@ -298,18 +302,24 @@ cm_start(struct torrent *tp)
cm->block_field = btpd_calloc(tp->meta.npieces * cm->bppbf, 1);

BTPDQ_INIT(&cm->todoq);
evtimer_set(&cm->save_timer, save_timer_cb, tp);

if ((err = bts_open(&cm->rds, &tp->meta, fd_cb_rd, tp)) != 0)
btpd_err("Error opening stream (%s).\n", strerror(err));
tp->cm = cm;
}

evtimer_set(&cm->save_timer, save_timer_cb, tp);
void
cm_start(struct torrent *tp)
{
struct content *cm = tp->cm;

if ((errno = bts_open(&cm->rds, &tp->meta, fd_cb_rd, tp)) != 0)
btpd_err("Error opening stream (%s).\n", strerror(errno));

cm->active = 1;
struct cm_op *op = btpd_calloc(1, sizeof(*op));
op->tp = tp;
op->type = CM_START;
add_todo(cm, op);
return 0;
}

int


+ 5
- 1
btpd/content.h Voir le fichier

@@ -3,9 +3,13 @@

void cm_init(void);

int cm_start(struct torrent *tp);
void cm_create(struct torrent *tp);
void cm_kill(struct torrent *tp);

void cm_start(struct torrent *tp);
void cm_stop(struct torrent * tp);

int cm_active(struct torrent *tp);
int cm_full(struct torrent *tp);

uint8_t *cm_get_piece_field(struct torrent *tp);


+ 20
- 5
btpd/net.c Voir le fichier

@@ -52,7 +52,7 @@ net_torrent_has_peer(struct net *n, const uint8_t *id)
}

void
net_add_torrent(struct torrent *tp)
net_create(struct torrent *tp)
{
size_t field_size = ceil(tp->meta.npieces / 8.0);
size_t mem = sizeof(*(tp->net)) + field_size +
@@ -62,21 +62,32 @@ net_add_torrent(struct torrent *tp)
n->tp = tp;
tp->net = n;

n->active = 1;
BTPDQ_INIT(&n->getlst);

n->busy_field = (uint8_t *)(n + 1);
n->piece_count = (unsigned *)(n->busy_field + field_size);
}

void
net_kill(struct torrent *tp)
{
free(tp->net);
tp->net = NULL;
}

void
net_start(struct torrent *tp)
{
struct net *n = tp->net;
BTPDQ_INSERT_HEAD(&m_torrents, n, entry);
m_ntorrents++;
n->active = 1;
}

void
net_del_torrent(struct torrent *tp)
net_stop(struct torrent *tp)
{
struct net *n = tp->net;
tp->net = NULL;

assert(m_ntorrents > 0);
m_ntorrents--;
@@ -104,8 +115,12 @@ net_del_torrent(struct torrent *tp)
peer_kill(p);
p = next;
}
}

free(n);
int
net_active(struct torrent *tp)
{
return tp->net->active;
}

void


+ 6
- 2
btpd/net.h Voir le fichier

@@ -20,8 +20,12 @@ extern unsigned net_npeers;

void net_init(void);

void net_add_torrent(struct torrent *tp);
void net_del_torrent(struct torrent *tp);
void net_create(struct torrent *tp);
void net_kill(struct torrent *tp);

void net_start(struct torrent *tp);
void net_stop(struct torrent *tp);
int net_active(struct torrent *tp);

int net_torrent_has_peer(struct net *n, const uint8_t *id);



+ 23
- 17
btpd/torrent.c Voir le fichier

@@ -126,11 +126,18 @@ torrent_start(const uint8_t *hash)
bcopy(relpath, tp->relpath, RELPATH_SIZE);
tp->meta = *mi;
free(mi);
BTPDQ_INSERT_TAIL(&m_torrents, tp, entry);
m_ntorrents++;
cm_start(tp);

return 0;
if ((error = tr_create(tp)) == 0) {
net_create(tp);
cm_create(tp);
BTPDQ_INSERT_TAIL(&m_torrents, tp, entry);
m_ntorrents++;
cm_start(tp);
} else {
clear_metainfo(&tp->meta);
free(tp);
}
return error;
}

void
@@ -140,16 +147,13 @@ torrent_stop(struct torrent *tp)
case T_STARTING:
case T_ACTIVE:
tp->state = T_STOPPING;
if (tp->tr != NULL)
tr_stop(tp);
if (tp->net != NULL)
net_del_torrent(tp);
if (tp->cm != NULL)
cm_stop(tp);
tr_stop(tp);
net_stop(tp);
cm_stop(tp);
break;
case T_STOPPING:
if (tp->tr != NULL)
tr_destroy(tp);
if (tr_active(tp))
tr_stop(tp);
break;
}
}
@@ -162,6 +166,9 @@ torrent_kill(struct torrent *tp)
m_ntorrents--;
BTPDQ_REMOVE(&m_torrents, tp, entry);
clear_metainfo(&tp->meta);
tr_kill(tp);
net_kill(tp);
cm_kill(tp);
free(tp);
if (m_ntorrents == 0)
btpd_on_no_torrents();
@@ -171,16 +178,15 @@ void
torrent_on_cm_started(struct torrent *tp)
{
tp->state = T_ACTIVE;
net_add_torrent(tp);
if (tr_start(tp) != 0)
torrent_stop(tp);
net_start(tp);
tr_start(tp);
}

void
torrent_on_cm_stopped(struct torrent *tp)
{
assert(tp->state == T_STOPPING);
if (tp->tr == NULL)
if (!tr_active(tp))
torrent_kill(tp);
}

@@ -188,6 +194,6 @@ void
torrent_on_tr_stopped(struct torrent *tp)
{
assert(tp->state == T_STOPPING);
if (tp->cm == NULL)
if (!cm_active(tp))
torrent_kill(tp);
}

+ 49
- 27
btpd/tracker_req.c Voir le fichier

@@ -37,7 +37,7 @@ struct tracker {

static void tr_send(struct torrent *tp, enum tr_event event);

void
static void
maybe_connect_to(struct torrent *tp, const char *pinfo)
{
const char *pid;
@@ -66,21 +66,25 @@ maybe_connect_to(struct torrent *tp, const char *pinfo)


static int
parse_reply(struct torrent *tp, const char *content, size_t size)
parse_reply(struct torrent *tp, const char *content, size_t size, int parse)
{
const char *buf;
size_t len;
const char *peers;
int interval;

if (benc_validate(content, size) != 0)
goto bad_data;

if ((buf = benc_dget_mem(content, "failure reason", &len)) != NULL) {
btpd_log(BTPD_L_ERROR, "Tracker failure: %.*s.\n", (int)len, buf);
return 1;
}

if ((benc_validate(content, size) != 0 ||
!benc_dct_chk(content, 2, BE_INT, 1, "interval",
BE_ANY, 1, "peers")))
if (!parse)
return 0;

if (!benc_dct_chk(content, 2, BE_INT, 1, "interval", BE_ANY, 1, "peers"))
goto bad_data;

interval = benc_dget_int(content, "interval");
@@ -109,6 +113,19 @@ bad_data:
return 1;
}

static void
tr_set_stopped(struct torrent *tp)
{
struct tracker *tr = tp->tr;
event_del(&tr->timer);
tr->ttype = TIMER_NONE;
if (tr->req != NULL) {
http_cancel(tr->req);
tr->req = NULL;
}
torrent_on_tr_stopped(tp);
}

static void
http_cb(struct http *req, struct http_res *res, void *arg)
{
@@ -116,9 +133,8 @@ http_cb(struct http *req, struct http_res *res, void *arg)
struct tracker *tr = tp->tr;
assert(tr->ttype == TIMER_TIMEOUT);
tr->req = NULL;
if (res->res == HRES_OK &&
(tr->event == TR_EV_STOPPED
|| parse_reply(tp, res->content, res->length) == 0)) {
if (res->res == HRES_OK && parse_reply(tp, res->content, res->length,
tr->event != TR_EV_STOPPED) == 0) {
tr->nerrors = 0;
tr->ttype = TIMER_INTERVAL;
event_add(&tr->timer, (& (struct timeval) { tr->interval, 0 }));
@@ -128,7 +144,7 @@ http_cb(struct http *req, struct http_res *res, void *arg)
event_add(&tr->timer, RETRY_WAIT);
}
if (tr->event == TR_EV_STOPPED && (tr->nerrors == 0 || tr->nerrors >= 5))
tr_destroy(tp);
tr_set_stopped(tp);
}

static void
@@ -138,17 +154,15 @@ timer_cb(int fd, short type, void *arg)
struct tracker *tr = tp->tr;
switch (tr->ttype) {
case TIMER_TIMEOUT:
btpd_log(BTPD_L_ERROR, "Tracker request timed out for '%s'.\n",
tp->meta.name);
tr->nerrors++;
if (tr->event == TR_EV_STOPPED && tr->nerrors >= 5) {
tr_destroy(tp);
tr_set_stopped(tp);
break;
}
case TIMER_RETRY:
if (tr->event == TR_EV_STOPPED) {
event_add(&tr->timer, REQ_TIMEOUT);
http_redo(&tr->req);
} else
tr_send(tp, tr->event);
tr_send(tp, tr->event);
break;
case TIMER_INTERVAL:
tr_send(tp, TR_EV_EMPTY);
@@ -188,27 +202,21 @@ tr_send(struct torrent *tp, enum tr_event event)
}

int
tr_start(struct torrent *tp)
tr_create(struct torrent *tp)
{
assert(tp->tr == NULL);
if (strncmp(tp->meta.announce, "http://", sizeof("http://") - 1) != 0) {
btpd_log(BTPD_L_ERROR,
"btpd currently has no support for the protocol specified in "
"'%s'.\n", tp->meta.announce);
return EINVAL;
}

struct tracker *tr = btpd_calloc(1, sizeof(*tr));
evtimer_set(&tr->timer, timer_cb, tp);
tp->tr = tr;

tr_send(tp, TR_EV_STARTED);

tp->tr = btpd_calloc(1, sizeof(*tp->tr));
evtimer_set(&tp->tr->timer, timer_cb, tp);
return 0;
}

void
tr_destroy(struct torrent *tp)
tr_kill(struct torrent *tp)
{
struct tracker *tr = tp->tr;
tp->tr = NULL;
@@ -216,7 +224,12 @@ tr_destroy(struct torrent *tp)
if (tr->req != NULL)
http_cancel(tr->req);
free(tr);
torrent_on_tr_stopped(tp);
}

void
tr_start(struct torrent *tp)
{
tr_send(tp, TR_EV_STARTED);
}

void
@@ -234,7 +247,16 @@ tr_complete(struct torrent *tp)
void
tr_stop(struct torrent *tp)
{
tr_send(tp, TR_EV_STOPPED);
if (tp->tr->event == TR_EV_STOPPED)
tr_set_stopped(tp);
else
tr_send(tp, TR_EV_STOPPED);
}

int
tr_active(struct torrent *tp)
{
return tp->tr->ttype != TIMER_NONE;
}

unsigned


+ 4
- 2
btpd/tracker_req.h Voir le fichier

@@ -1,11 +1,13 @@
#ifndef TRACKER_REQ_H
#define TRACKER_REQ_H

int tr_start(struct torrent *tp);
int tr_create(struct torrent *tp);
void tr_kill(struct torrent *tp);
void tr_start(struct torrent *tp);
void tr_stop(struct torrent *tp);
void tr_refresh(struct torrent *tp);
void tr_complete(struct torrent *tp);
void tr_destroy(struct torrent *tp);
unsigned tr_errors(struct torrent *tp);
int tr_active(struct torrent *tp);

#endif

Chargement…
Annuler
Enregistrer