* Renamed the policy* files to upload* and download*. * The upload (un)choker is now global instead of per torrent. The algorithm is not yet implemented however. To be continued...master
@@ -8,9 +8,10 @@ btpd_SOURCES=\ | |||
net_buf.c net_buf.h\ | |||
queue.h \ | |||
peer.c peer.h\ | |||
policy_choke.c policy_if.c policy_subr.c policy.h\ | |||
download.c download_subr.c download.h\ | |||
torrent.c torrent.h\ | |||
tracker_req.c tracker_req.h | |||
tracker_req.c tracker_req.h\ | |||
upload.c upload.h | |||
btpd_LDADD=../misc/libmisc.a -levent -lcrypto -lm | |||
btpd_CPPFLAGS=-I$(top_srcdir)/misc @event_CPPFLAGS@ @openssl_CPPFLAGS@ | |||
@@ -37,7 +37,6 @@ struct child { | |||
BTPDQ_HEAD(child_tq, child); | |||
static uint8_t m_peer_id[20]; | |||
static struct event m_heartbeat; | |||
static struct event m_sigint; | |||
static struct event m_sigterm; | |||
static struct event m_sigchld; | |||
@@ -45,8 +44,6 @@ static struct child_tq m_kids = BTPDQ_HEAD_INITIALIZER(m_kids); | |||
static unsigned m_ntorrents; | |||
static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents); | |||
unsigned long btpd_seconds; | |||
void | |||
btpd_shutdown(void) | |||
{ | |||
@@ -98,19 +95,6 @@ child_cb(int signal, short type, void *arg) | |||
} | |||
} | |||
static void | |||
heartbeat_cb(int sd, short type, void *arg) | |||
{ | |||
struct torrent *tp; | |||
btpd_seconds++; | |||
BTPDQ_FOREACH(tp, &m_torrents, entry) | |||
dl_by_second(tp); | |||
evtimer_add(&m_heartbeat, (& (struct timeval) { 1, 0 })); | |||
} | |||
void | |||
btpd_add_torrent(struct torrent *tp) | |||
{ | |||
@@ -165,6 +149,7 @@ btpd_init(void) | |||
net_init(); | |||
ipc_init(); | |||
ul_init(); | |||
signal(SIGPIPE, SIG_IGN); | |||
@@ -174,7 +159,4 @@ btpd_init(void) | |||
signal_add(&m_sigterm, NULL); | |||
signal_set(&m_sigchld, SIGCHLD, child_cb, NULL); | |||
signal_add(&m_sigchld, NULL); | |||
evtimer_set(&m_heartbeat, heartbeat_cb, NULL); | |||
evtimer_add(&m_heartbeat, (& (struct timeval) { 1, 0 })); | |||
} |
@@ -22,15 +22,14 @@ | |||
#include "net.h" | |||
#include "peer.h" | |||
#include "torrent.h" | |||
#include "policy.h" | |||
#include "download.h" | |||
#include "upload.h" | |||
#include "subr.h" | |||
#include "opts.h" | |||
#define BTPD_VERSION (PACKAGE_NAME "/" PACKAGE_VERSION) | |||
extern unsigned long btpd_seconds; | |||
#define BTPD_L_ALL 0xffffffff | |||
#define BTPD_L_ERROR 0x00000001 | |||
#define BTPD_L_TRACKER 0x00000002 | |||
@@ -38,7 +38,6 @@ cmd_stat(int argc, const char *args, FILE *fp) | |||
errdie(buf_swrite(&iob, "d")); | |||
errdie(buf_print(&iob, "6:npeersi%ue", net_npeers)); | |||
errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents())); | |||
errdie(buf_print(&iob, "7:secondsi%lue", btpd_seconds)); | |||
errdie(buf_swrite(&iob, "8:torrentsl")); | |||
BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | |||
uint32_t seen_npieces = 0; | |||
@@ -4,19 +4,6 @@ | |||
#include "btpd.h" | |||
#include "tracker_req.h" | |||
void | |||
dl_by_second(struct torrent *tp) | |||
{ | |||
if (btpd_seconds == tp->tracker_time) | |||
tracker_req(tp, TR_EMPTY); | |||
if (btpd_seconds == tp->opt_time) | |||
next_optimistic(tp, NULL); | |||
if (btpd_seconds == tp->choke_time) | |||
choke_alg(tp); | |||
} | |||
/* | |||
* Called when a peer announces it's got a new piece. | |||
* | |||
@@ -87,32 +74,6 @@ dl_on_choke(struct peer *p) | |||
dl_on_undownload(p); | |||
} | |||
void | |||
dl_on_upload(struct peer *p) | |||
{ | |||
choke_alg(p->tp); | |||
} | |||
void | |||
dl_on_interest(struct peer *p) | |||
{ | |||
if ((p->flags & PF_I_CHOKE) == 0) | |||
dl_on_upload(p); | |||
} | |||
void | |||
dl_on_unupload(struct peer *p) | |||
{ | |||
choke_alg(p->tp); | |||
} | |||
void | |||
dl_on_uninterest(struct peer *p) | |||
{ | |||
if ((p->flags & PF_I_CHOKE) == 0) | |||
dl_on_unupload(p); | |||
} | |||
/** | |||
* Called when a piece has been tested positively. | |||
*/ | |||
@@ -181,20 +142,11 @@ void | |||
dl_on_new_peer(struct peer *p) | |||
{ | |||
struct torrent *tp = p->tp; | |||
tp->npeers++; | |||
p->flags |= PF_ATTACHED; | |||
BTPDQ_REMOVE(&net_unattached, p, p_entry); | |||
if (tp->npeers == 1) { | |||
BTPDQ_INSERT_HEAD(&tp->peers, p, p_entry); | |||
next_optimistic(tp, p); | |||
} else { | |||
if (random() > RAND_MAX / 3) | |||
BTPDQ_INSERT_AFTER(&tp->peers, tp->optimistic, p, p_entry); | |||
else | |||
BTPDQ_INSERT_TAIL(&tp->peers, p, p_entry); | |||
} | |||
BTPDQ_INSERT_HEAD(&tp->peers, p, p_entry); | |||
ul_on_new_peer(p); | |||
} | |||
void | |||
@@ -202,26 +154,15 @@ dl_on_lost_peer(struct peer *p) | |||
{ | |||
struct torrent *tp = p->tp; | |||
assert(tp->npeers > 0 && (p->flags & PF_ATTACHED) != 0); | |||
tp->npeers--; | |||
p->flags &= ~PF_ATTACHED; | |||
if (tp->npeers == 0) { | |||
BTPDQ_REMOVE(&tp->peers, p, p_entry); | |||
tp->optimistic = NULL; | |||
tp->choke_time = tp->opt_time = 0; | |||
} else if (tp->optimistic == p) { | |||
struct peer *next = BTPDQ_NEXT(p, p_entry); | |||
BTPDQ_REMOVE(&tp->peers, p, p_entry); | |||
next_optimistic(tp, next); | |||
} else if ((p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT) { | |||
BTPDQ_REMOVE(&tp->peers, p, p_entry); | |||
dl_on_unupload(p); | |||
} else { | |||
BTPDQ_REMOVE(&tp->peers, p, p_entry); | |||
} | |||
ul_on_lost_peer(p); | |||
for (uint32_t i = 0; i < tp->meta.npieces; i++) | |||
if (peer_has(p, i)) | |||
tp->piece_count[i]--; | |||
if (peer_has(p, i)) | |||
tp->piece_count[i]--; | |||
if (p->nreqs_out > 0) | |||
dl_on_undownload(p); |
@@ -1,12 +1,7 @@ | |||
#ifndef BTPD_POLICY_H | |||
#define BTPD_POLICY_H | |||
#ifndef BTPD_DOWNLOAD_H | |||
#define BTPD_DOWNLOAD_H | |||
// policy_choke.c | |||
void choke_alg(struct torrent *tp); | |||
void next_optimistic(struct torrent *tp, struct peer *np); | |||
// policy_subr.c | |||
// download_subr.c | |||
int piece_full(struct piece *pc); | |||
void piece_free(struct piece *pc); | |||
@@ -23,19 +18,13 @@ void dl_unassign_requests(struct peer *p); | |||
void dl_unassign_requests_eg(struct peer *p); | |||
void dl_piece_reorder_eg(struct piece *pc); | |||
// policy_if.c | |||
void dl_by_second(struct torrent *tp); | |||
// download.c | |||
void dl_on_new_peer(struct peer *p); | |||
void dl_on_lost_peer(struct peer *p); | |||
void dl_on_choke(struct peer *p); | |||
void dl_on_unchoke(struct peer *p); | |||
void dl_on_upload(struct peer *p); | |||
void dl_on_unupload(struct peer *p); | |||
void dl_on_interest(struct peer *p); | |||
void dl_on_uninterest(struct peer *p); | |||
void dl_on_download(struct peer *p); | |||
void dl_on_undownload(struct peer *p); | |||
void dl_on_piece_ann(struct peer *p, uint32_t index); |
@@ -1,3 +1,6 @@ | |||
#ifndef BTPD_OPTS_H | |||
#define BTPD_OPTS_H | |||
extern short btpd_daemon; | |||
extern const char *btpd_dir; | |||
extern uint32_t btpd_logmask; | |||
@@ -5,3 +8,5 @@ extern unsigned net_max_peers; | |||
extern unsigned net_bw_limit_in; | |||
extern unsigned net_bw_limit_out; | |||
extern int net_port; | |||
#endif |
@@ -383,7 +383,7 @@ peer_on_interest(struct peer *p) | |||
return; | |||
else { | |||
p->flags |= PF_P_WANT; | |||
dl_on_interest(p); | |||
ul_on_interest(p); | |||
} | |||
} | |||
@@ -395,7 +395,7 @@ peer_on_uninterest(struct peer *p) | |||
return; | |||
else { | |||
p->flags &= ~PF_P_WANT; | |||
dl_on_uninterest(p); | |||
ul_on_uninterest(p); | |||
} | |||
} | |||
@@ -61,7 +61,7 @@ struct peer { | |||
} net; | |||
BTPDQ_ENTRY(peer) p_entry; | |||
BTPDQ_ENTRY(peer) ul_entry; | |||
BTPDQ_ENTRY(peer) rq_entry; | |||
BTPDQ_ENTRY(peer) wq_entry; | |||
}; | |||
@@ -1,90 +0,0 @@ | |||
#include "btpd.h" | |||
static int | |||
rate_cmp(long rate1, long rate2) | |||
{ | |||
if (rate1 < rate2) | |||
return -1; | |||
else if (rate1 == rate2) | |||
return 0; | |||
else | |||
return 1; | |||
} | |||
static int | |||
dwnrate_cmp(const void *p1, const void *p2) | |||
{ | |||
long rate1 = (*(struct peer **)p1)->rate_dwn; | |||
long rate2 = (*(struct peer **)p2)->rate_dwn; | |||
return rate_cmp(rate1, rate2); | |||
} | |||
static int | |||
uprate_cmp(const void *p1, const void *p2) | |||
{ | |||
long rate1 = (*(struct peer **)p1)->rate_up; | |||
long rate2 = (*(struct peer **)p2)->rate_up; | |||
return rate_cmp(rate1, rate2); | |||
} | |||
void | |||
choke_alg(struct torrent *tp) | |||
{ | |||
assert(tp->npeers > 0); | |||
int i; | |||
struct peer *p; | |||
struct peer *psort[tp->npeers]; | |||
i = 0; | |||
BTPDQ_FOREACH(p, &tp->peers, p_entry) | |||
psort[i++] = p; | |||
if (tp->have_npieces == tp->meta.npieces) | |||
qsort(psort, tp->npeers, sizeof(p), uprate_cmp); | |||
else | |||
qsort(psort, tp->npeers, sizeof(p), dwnrate_cmp); | |||
tp->ndown = 0; | |||
if (tp->optimistic != NULL) { | |||
if (tp->optimistic->flags & PF_I_CHOKE) | |||
peer_unchoke(tp->optimistic); | |||
if (tp->optimistic->flags & PF_P_WANT) | |||
tp->ndown = 1; | |||
} | |||
for (i = tp->npeers - 1; i >= 0; i--) { | |||
if (psort[i] == tp->optimistic) | |||
continue; | |||
if (tp->ndown < 4) { | |||
if (psort[i]->flags & PF_P_WANT) | |||
tp->ndown++; | |||
if (psort[i]->flags & PF_I_CHOKE) | |||
peer_unchoke(psort[i]); | |||
} else { | |||
if ((psort[i]->flags & PF_I_CHOKE) == 0) | |||
peer_choke(psort[i]); | |||
} | |||
} | |||
tp->choke_time = btpd_seconds + 10; | |||
} | |||
void | |||
next_optimistic(struct torrent *tp, struct peer *np) | |||
{ | |||
if (np != NULL) | |||
tp->optimistic = np; | |||
else if (tp->optimistic == NULL) | |||
tp->optimistic = BTPDQ_FIRST(&tp->peers); | |||
else { | |||
np = BTPDQ_NEXT(tp->optimistic, p_entry); | |||
if (np != NULL) | |||
tp->optimistic = np; | |||
else | |||
tp->optimistic = BTPDQ_FIRST(&tp->peers); | |||
} | |||
assert(tp->optimistic != NULL); | |||
choke_alg(tp); | |||
tp->opt_time = btpd_seconds + 30; | |||
} |
@@ -52,10 +52,6 @@ struct torrent { | |||
uint64_t uploaded, downloaded; | |||
unsigned long choke_time; | |||
unsigned long opt_time; | |||
unsigned long tracker_time; | |||
short ndown; | |||
struct peer *optimistic; | |||
@@ -100,7 +100,7 @@ tracker_done(pid_t pid, void *arg) | |||
goto out; | |||
} | |||
tp->tracker_time = btpd_seconds + interval; | |||
//tp->tracker_time = btpd_seconds + interval; | |||
int error = 0; | |||
size_t length; | |||
@@ -134,7 +134,7 @@ out: | |||
"Start request failed for %s.\n", tp->relpath); | |||
torrent_unload(tp); | |||
} else | |||
tp->tracker_time = btpd_seconds + 10; | |||
;//tp->tracker_time = btpd_seconds + 10; | |||
} | |||
munmap(req->res, REQ_SIZE); | |||
free(req); | |||
@@ -0,0 +1,72 @@ | |||
#include "btpd.h" | |||
static struct event m_choke_timer; | |||
static unsigned m_npeers; | |||
static struct peer_tq m_peerq = BTPDQ_HEAD_INITIALIZER(m_peerq); | |||
static void | |||
choke_do(void) | |||
{ | |||
struct peer *p; | |||
BTPDQ_FOREACH(p, &m_peerq, ul_entry) | |||
if (p->flags & PF_I_CHOKE) | |||
peer_unchoke(p); | |||
} | |||
static void | |||
choke_cb(int sd, short type, void *arg) | |||
{ | |||
evtimer_add(&m_choke_timer, (& (struct timeval) { 10, 0})); | |||
choke_do(); | |||
} | |||
void | |||
ul_on_new_peer(struct peer *p) | |||
{ | |||
m_npeers++; | |||
BTPDQ_INSERT_HEAD(&m_peerq, p, ul_entry); | |||
choke_do(); | |||
} | |||
void | |||
ul_on_lost_peer(struct peer *p) | |||
{ | |||
assert(m_npeers > 0); | |||
BTPDQ_REMOVE(&m_peerq, p, ul_entry); | |||
m_npeers--; | |||
if ((p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT) | |||
choke_do(); | |||
} | |||
void | |||
ul_on_lost_torrent(struct torrent *tp) | |||
{ | |||
struct peer *p; | |||
BTPDQ_FOREACH(p, &tp->peers, p_entry) { | |||
BTPDQ_REMOVE(&m_peerq, p, ul_entry); | |||
m_npeers--; | |||
} | |||
choke_do(); | |||
} | |||
void | |||
ul_on_interest(struct peer *p) | |||
{ | |||
if ((p->flags & PF_I_CHOKE) == 0) | |||
choke_do(); | |||
} | |||
void | |||
ul_on_uninterest(struct peer *p) | |||
{ | |||
if ((p->flags & PF_I_CHOKE) == 0) | |||
choke_do(); | |||
} | |||
void | |||
ul_init(void) | |||
{ | |||
evtimer_set(&m_choke_timer, choke_cb, NULL); | |||
evtimer_add(&m_choke_timer, (& (struct timeval) { 10, 0 })); | |||
} |
@@ -0,0 +1,11 @@ | |||
#ifndef BTPD_UPLOAD_H | |||
#define BTPD_UPLOAD_H | |||
void ul_on_new_peer(struct peer *p); | |||
void ul_on_lost_peer(struct peer *p); | |||
void ul_on_lost_torrent(struct torrent *tp); | |||
void ul_on_interest(struct peer *p); | |||
void ul_on_uninterest(struct peer *p); | |||
void ul_init(void); | |||
#endif |