瀏覽代碼

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 年之前
父節點
當前提交
c8f9335e6e
共有 6 個文件被更改,包括 113 次插入19 次删除
  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 查看文件

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

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);
while (tp != NULL) {
struct torrent *next = BTPDQ_NEXT(tp, entry);
static void
grace_cb(int fd, short type, void *arg)
{
struct torrent *tp;
BTPDQ_FOREACH(tp, &m_torrents, entry)
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
signal_cb(int signal, short type, void *arg)
{
btpd_log(BTPD_L_BTPD, "Got signal %d.\n", signal);
btpd_shutdown();
btpd_shutdown((& (struct timeval) { 30, 0 }));
}

void


+ 4
- 1
btpd/btpd.h 查看文件

@@ -48,7 +48,7 @@ void btpd_err(const char *fmt, ...);
void *btpd_malloc(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);
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_end(void);

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

#endif

+ 39
- 8
btpd/torrent.c 查看文件

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

void
torrent_deactivate(struct torrent *tp)
{
tp->state = T_STOPPING;
tr_stop(tp);
net_del_torrent(tp);
cm_stop(tp);
switch (tp->state) {
case T_INACTIVE:
break;
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
@@ -110,5 +128,18 @@ void
torrent_on_cm_stopped(struct torrent *tp)
{
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 查看文件

@@ -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_started(struct torrent *tp);
void torrent_on_tr_stopped(struct torrent *tp);

#endif

+ 28
- 1
btpd/tracker_req.c 查看文件

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

#define REQ_TIMEOUT (& (struct timeval) { 120, 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 tracker *tr = tp->tr;
assert(tr->ttype == TIMER_TIMEOUT);
tr->req = NULL;
if ((http_succeeded(res) &&
parse_reply(tp, res->content, res->length) == 0)) {
tr->nerrors = 0;
tr->ttype = TIMER_INTERVAL;
event_add(&tr->timer, (& (struct timeval) { tr->interval, 0 }));
} else {
tr->nerrors++;
tr->ttype = TIMER_RETRY;
event_add(&tr->timer, RETRY_WAIT);
}
if (tr->event == TR_EV_STOPPED && (tr->nerrors == 0 || tr->nerrors >= 5))
tr_destroy(tp);
}

static void
@@ -145,8 +151,17 @@ timer_cb(int fd, short type, void *arg)
struct tracker *tr = tp->tr;
switch (tr->ttype) {
case TIMER_TIMEOUT:
tr->nerrors++;
if (tr->event == TR_EV_STOPPED && tr->nerrors >= 5) {
tr_destroy(tp);
break;
}
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;
case TIMER_INTERVAL:
tr_send(tp, TR_EV_EMPTY);
@@ -205,6 +220,18 @@ tr_start(struct torrent *tp)
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
tr_refresh(struct torrent *tp)
{


+ 1
- 0
btpd/tracker_req.h 查看文件

@@ -5,5 +5,6 @@ int 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);

#endif

Loading…
取消
儲存