* 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\ | net_buf.c net_buf.h\ | ||||
queue.h \ | queue.h \ | ||||
peer.c peer.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\ | 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_LDADD=../misc/libmisc.a -levent -lcrypto -lm | ||||
btpd_CPPFLAGS=-I$(top_srcdir)/misc @event_CPPFLAGS@ @openssl_CPPFLAGS@ | btpd_CPPFLAGS=-I$(top_srcdir)/misc @event_CPPFLAGS@ @openssl_CPPFLAGS@ | ||||
@@ -37,7 +37,6 @@ struct child { | |||||
BTPDQ_HEAD(child_tq, child); | BTPDQ_HEAD(child_tq, child); | ||||
static uint8_t m_peer_id[20]; | static uint8_t m_peer_id[20]; | ||||
static struct event m_heartbeat; | |||||
static struct event m_sigint; | static struct event m_sigint; | ||||
static struct event m_sigterm; | static struct event m_sigterm; | ||||
static struct event m_sigchld; | 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 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); | ||||
unsigned long btpd_seconds; | |||||
void | void | ||||
btpd_shutdown(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 | void | ||||
btpd_add_torrent(struct torrent *tp) | btpd_add_torrent(struct torrent *tp) | ||||
{ | { | ||||
@@ -165,6 +149,7 @@ btpd_init(void) | |||||
net_init(); | net_init(); | ||||
ipc_init(); | ipc_init(); | ||||
ul_init(); | |||||
signal(SIGPIPE, SIG_IGN); | signal(SIGPIPE, SIG_IGN); | ||||
@@ -174,7 +159,4 @@ btpd_init(void) | |||||
signal_add(&m_sigterm, NULL); | signal_add(&m_sigterm, NULL); | ||||
signal_set(&m_sigchld, SIGCHLD, child_cb, NULL); | signal_set(&m_sigchld, SIGCHLD, child_cb, NULL); | ||||
signal_add(&m_sigchld, 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 "net.h" | ||||
#include "peer.h" | #include "peer.h" | ||||
#include "torrent.h" | #include "torrent.h" | ||||
#include "policy.h" | |||||
#include "download.h" | |||||
#include "upload.h" | |||||
#include "subr.h" | #include "subr.h" | ||||
#include "opts.h" | #include "opts.h" | ||||
#define BTPD_VERSION (PACKAGE_NAME "/" PACKAGE_VERSION) | #define BTPD_VERSION (PACKAGE_NAME "/" PACKAGE_VERSION) | ||||
extern unsigned long btpd_seconds; | |||||
#define BTPD_L_ALL 0xffffffff | #define BTPD_L_ALL 0xffffffff | ||||
#define BTPD_L_ERROR 0x00000001 | #define BTPD_L_ERROR 0x00000001 | ||||
#define BTPD_L_TRACKER 0x00000002 | #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_swrite(&iob, "d")); | ||||
errdie(buf_print(&iob, "6:npeersi%ue", net_npeers)); | errdie(buf_print(&iob, "6:npeersi%ue", net_npeers)); | ||||
errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents())); | 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")); | errdie(buf_swrite(&iob, "8:torrentsl")); | ||||
BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | ||||
uint32_t seen_npieces = 0; | uint32_t seen_npieces = 0; | ||||
@@ -4,19 +4,6 @@ | |||||
#include "btpd.h" | #include "btpd.h" | ||||
#include "tracker_req.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. | * 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); | 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. | * Called when a piece has been tested positively. | ||||
*/ | */ | ||||
@@ -181,20 +142,11 @@ void | |||||
dl_on_new_peer(struct peer *p) | dl_on_new_peer(struct peer *p) | ||||
{ | { | ||||
struct torrent *tp = p->tp; | struct torrent *tp = p->tp; | ||||
tp->npeers++; | tp->npeers++; | ||||
p->flags |= PF_ATTACHED; | p->flags |= PF_ATTACHED; | ||||
BTPDQ_REMOVE(&net_unattached, p, p_entry); | 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 | void | ||||
@@ -202,26 +154,15 @@ dl_on_lost_peer(struct peer *p) | |||||
{ | { | ||||
struct torrent *tp = p->tp; | struct torrent *tp = p->tp; | ||||
assert(tp->npeers > 0 && (p->flags & PF_ATTACHED) != 0); | |||||
tp->npeers--; | tp->npeers--; | ||||
p->flags &= ~PF_ATTACHED; | 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++) | 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) | if (p->nreqs_out > 0) | ||||
dl_on_undownload(p); | 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); | int piece_full(struct piece *pc); | ||||
void piece_free(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_unassign_requests_eg(struct peer *p); | ||||
void dl_piece_reorder_eg(struct piece *pc); | 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_new_peer(struct peer *p); | ||||
void dl_on_lost_peer(struct peer *p); | void dl_on_lost_peer(struct peer *p); | ||||
void dl_on_choke(struct peer *p); | void dl_on_choke(struct peer *p); | ||||
void dl_on_unchoke(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_download(struct peer *p); | ||||
void dl_on_undownload(struct peer *p); | void dl_on_undownload(struct peer *p); | ||||
void dl_on_piece_ann(struct peer *p, uint32_t index); | 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 short btpd_daemon; | ||||
extern const char *btpd_dir; | extern const char *btpd_dir; | ||||
extern uint32_t btpd_logmask; | 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_in; | ||||
extern unsigned net_bw_limit_out; | extern unsigned net_bw_limit_out; | ||||
extern int net_port; | extern int net_port; | ||||
#endif |
@@ -383,7 +383,7 @@ peer_on_interest(struct peer *p) | |||||
return; | return; | ||||
else { | else { | ||||
p->flags |= PF_P_WANT; | p->flags |= PF_P_WANT; | ||||
dl_on_interest(p); | |||||
ul_on_interest(p); | |||||
} | } | ||||
} | } | ||||
@@ -395,7 +395,7 @@ peer_on_uninterest(struct peer *p) | |||||
return; | return; | ||||
else { | else { | ||||
p->flags &= ~PF_P_WANT; | p->flags &= ~PF_P_WANT; | ||||
dl_on_uninterest(p); | |||||
ul_on_uninterest(p); | |||||
} | } | ||||
} | } | ||||
@@ -61,7 +61,7 @@ struct peer { | |||||
} net; | } net; | ||||
BTPDQ_ENTRY(peer) p_entry; | BTPDQ_ENTRY(peer) p_entry; | ||||
BTPDQ_ENTRY(peer) ul_entry; | |||||
BTPDQ_ENTRY(peer) rq_entry; | BTPDQ_ENTRY(peer) rq_entry; | ||||
BTPDQ_ENTRY(peer) wq_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; | uint64_t uploaded, downloaded; | ||||
unsigned long choke_time; | |||||
unsigned long opt_time; | |||||
unsigned long tracker_time; | |||||
short ndown; | short ndown; | ||||
struct peer *optimistic; | struct peer *optimistic; | ||||
@@ -100,7 +100,7 @@ tracker_done(pid_t pid, void *arg) | |||||
goto out; | goto out; | ||||
} | } | ||||
tp->tracker_time = btpd_seconds + interval; | |||||
//tp->tracker_time = btpd_seconds + interval; | |||||
int error = 0; | int error = 0; | ||||
size_t length; | size_t length; | ||||
@@ -134,7 +134,7 @@ out: | |||||
"Start request failed for %s.\n", tp->relpath); | "Start request failed for %s.\n", tp->relpath); | ||||
torrent_unload(tp); | torrent_unload(tp); | ||||
} else | } else | ||||
tp->tracker_time = btpd_seconds + 10; | |||||
;//tp->tracker_time = btpd_seconds + 10; | |||||
} | } | ||||
munmap(req->res, REQ_SIZE); | munmap(req->res, REQ_SIZE); | ||||
free(req); | 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 |