Browse Source

Torrents can now be deactivated and btpd will wait for all torrents to

deactivate on shutdown. To not risk hanging indefinitely on unresponsive
trackers, btpd will cancel tracker requests after a while.
master
Richard Nyberg 19 years ago
parent
commit
c8f9335e6e
6 changed files with 113 additions and 19 deletions
  1. +40
    -9
      btpd/btpd.c
  2. +4
    -1
      btpd/btpd.h
  3. +39
    -8
      btpd/torrent.c
  4. +1
    -0
      btpd/torrent.h
  5. +28
    -1
      btpd/tracker_req.c
  6. +1
    -0
      btpd/tracker_req.h

+ 40
- 9
btpd/btpd.c View File

@@ -34,27 +34,58 @@ static struct event m_sigint;
static struct event m_sigterm; static struct event m_sigterm;
static unsigned m_ntorrents; static unsigned m_ntorrents;
static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents); static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);
static unsigned m_nactive;
static int m_shutdown;


void void
btpd_shutdown(void) btpd_exit(int code)
{ {
struct torrent *tp; btpd_log(BTPD_L_BTPD, "Exiting.\n");
exit(code);
}

void
btpd_tp_activated(struct torrent *tp)
{
m_nactive++;
}

void
btpd_tp_deactivated(struct torrent *tp)
{
m_nactive--;
if (m_nactive == 0 && m_shutdown)
btpd_exit(0);
}


tp = BTPDQ_FIRST(&m_torrents); static void
while (tp != NULL) { grace_cb(int fd, short type, void *arg)
struct torrent *next = BTPDQ_NEXT(tp, entry); {
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, entry)
torrent_deactivate(tp); torrent_deactivate(tp);
tp = next; }

void
btpd_shutdown(struct timeval *grace_tv)
{
if (m_nactive == 0)
btpd_exit(0);
else {
struct torrent *tp;
m_shutdown = 1;
BTPDQ_FOREACH(tp, &m_torrents, entry)
torrent_deactivate(tp);
if (grace_tv != NULL)
event_once(-1, EV_TIMEOUT, grace_cb, NULL, grace_tv);
} }
btpd_log(BTPD_L_BTPD, "Exiting.\n");
exit(0);
} }


static void static void
signal_cb(int signal, short type, void *arg) signal_cb(int signal, short type, void *arg)
{ {
btpd_log(BTPD_L_BTPD, "Got signal %d.\n", signal); btpd_log(BTPD_L_BTPD, "Got signal %d.\n", signal);
btpd_shutdown(); btpd_shutdown((& (struct timeval) { 30, 0 }));
} }


void void


+ 4
- 1
btpd/btpd.h View File

@@ -48,7 +48,7 @@ void btpd_err(const char *fmt, ...);
void *btpd_malloc(size_t size); void *btpd_malloc(size_t size);
void *btpd_calloc(size_t nmemb, size_t size); void *btpd_calloc(size_t nmemb, size_t size);


void btpd_shutdown(void); void btpd_shutdown(struct timeval *grace_tv);


struct torrent * btpd_get_torrent(const uint8_t *hash); struct torrent * btpd_get_torrent(const uint8_t *hash);
const struct torrent_tq *btpd_get_torrents(void); const struct torrent_tq *btpd_get_torrents(void);
@@ -64,4 +64,7 @@ void td_release_lock(void);
void td_post(void (*fun)(void *), void *arg); void td_post(void (*fun)(void *), void *arg);
void td_post_end(void); void td_post_end(void);


void btpd_tp_activated(struct torrent *tp);
void btpd_tp_deactivated(struct torrent *tp);

#endif #endif

+ 39
- 8
btpd/torrent.c View File

@@ -51,18 +51,36 @@ torrent_block_size(struct torrent *tp, uint32_t piece, uint32_t nblocks,
void void
torrent_activate(struct torrent *tp) torrent_activate(struct torrent *tp)
{ {
assert(tp->state == T_INACTIVE); if (tp->state == T_INACTIVE) {
tp->state = T_STARTING; tp->state = T_STARTING;
cm_start(tp); cm_start(tp);
btpd_tp_activated(tp);
}
} }


void void
torrent_deactivate(struct torrent *tp) torrent_deactivate(struct torrent *tp)
{ {
tp->state = T_STOPPING; switch (tp->state) {
tr_stop(tp); case T_INACTIVE:
net_del_torrent(tp); break;
cm_stop(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);
break;
case T_STOPPING:
if (tp->tr != NULL)
tr_destroy(tp);
break;
default:
abort();
}
} }


int int
@@ -110,5 +128,18 @@ void
torrent_on_cm_stopped(struct torrent *tp) torrent_on_cm_stopped(struct torrent *tp)
{ {
assert(tp->state == T_STOPPING); assert(tp->state == T_STOPPING);
tp->state = T_INACTIVE; if (tp->tr == NULL) {
tp->state = T_INACTIVE;
btpd_tp_deactivated(tp);
}
}

void
torrent_on_tr_stopped(struct torrent *tp)
{
assert(tp->state == T_STOPPING);
if (tp->cm == NULL) {
tp->state = T_INACTIVE;
btpd_tp_deactivated(tp);
}
} }

+ 1
- 0
btpd/torrent.h View File

@@ -36,5 +36,6 @@ uint32_t torrent_block_size(struct torrent *tp, uint32_t piece,


void torrent_on_cm_stopped(struct torrent *tp); void torrent_on_cm_stopped(struct torrent *tp);
void torrent_on_cm_started(struct torrent *tp); void torrent_on_cm_started(struct torrent *tp);
void torrent_on_tr_stopped(struct torrent *tp);


#endif #endif

+ 28
- 1
btpd/tracker_req.c View File

@@ -5,6 +5,7 @@
#include "benc.h" #include "benc.h"
#include "subr.h" #include "subr.h"
#include "http.h" #include "http.h"
#include "tracker_req.h"


#define REQ_TIMEOUT (& (struct timeval) { 120, 0 }) #define REQ_TIMEOUT (& (struct timeval) { 120, 0 })
#define RETRY_WAIT (& (struct timeval) { rand_between(35, 70), 0 }) #define RETRY_WAIT (& (struct timeval) { rand_between(35, 70), 0 })
@@ -128,14 +129,19 @@ http_cb(struct http *req, struct http_res *res, void *arg)
struct torrent *tp = arg; struct torrent *tp = arg;
struct tracker *tr = tp->tr; struct tracker *tr = tp->tr;
assert(tr->ttype == TIMER_TIMEOUT); assert(tr->ttype == TIMER_TIMEOUT);
tr->req = NULL;
if ((http_succeeded(res) && if ((http_succeeded(res) &&
parse_reply(tp, res->content, res->length) == 0)) { parse_reply(tp, res->content, res->length) == 0)) {
tr->nerrors = 0;
tr->ttype = TIMER_INTERVAL; tr->ttype = TIMER_INTERVAL;
event_add(&tr->timer, (& (struct timeval) { tr->interval, 0 })); event_add(&tr->timer, (& (struct timeval) { tr->interval, 0 }));
} else { } else {
tr->nerrors++;
tr->ttype = TIMER_RETRY; tr->ttype = TIMER_RETRY;
event_add(&tr->timer, RETRY_WAIT); event_add(&tr->timer, RETRY_WAIT);
} }
if (tr->event == TR_EV_STOPPED && (tr->nerrors == 0 || tr->nerrors >= 5))
tr_destroy(tp);
} }


static void static void
@@ -145,8 +151,17 @@ timer_cb(int fd, short type, void *arg)
struct tracker *tr = tp->tr; struct tracker *tr = tp->tr;
switch (tr->ttype) { switch (tr->ttype) {
case TIMER_TIMEOUT: case TIMER_TIMEOUT:
tr->nerrors++;
if (tr->event == TR_EV_STOPPED && tr->nerrors >= 5) {
tr_destroy(tp);
break;
}
case TIMER_RETRY: case TIMER_RETRY:
tr_send(tp, tp->tr->event); if (tr->event == TR_EV_STOPPED) {
event_add(&tr->timer, REQ_TIMEOUT);
http_redo(&tr->req);
} else
tr_send(tp, tr->event);
break; break;
case TIMER_INTERVAL: case TIMER_INTERVAL:
tr_send(tp, TR_EV_EMPTY); tr_send(tp, TR_EV_EMPTY);
@@ -205,6 +220,18 @@ tr_start(struct torrent *tp)
return 0; return 0;
} }


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

void void
tr_refresh(struct torrent *tp) tr_refresh(struct torrent *tp)
{ {


+ 1
- 0
btpd/tracker_req.h View File

@@ -5,5 +5,6 @@ int tr_start(struct torrent *tp);
void tr_stop(struct torrent *tp); void tr_stop(struct torrent *tp);
void tr_refresh(struct torrent *tp); void tr_refresh(struct torrent *tp);
void tr_complete(struct torrent *tp); void tr_complete(struct torrent *tp);
void tr_destroy(struct torrent *tp);


#endif #endif

||||||
x
 
000:0
Loading…
Cancel
Save