소스 검색

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

불러오는 중...
취소
저장