瀏覽代碼

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 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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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…
取消
儲存