diff --git a/btpd/http.c b/btpd/http.c index 9f57212..f1e6b7e 100644 --- a/btpd/http.c +++ b/btpd/http.c @@ -19,6 +19,7 @@ enum http_state { }; struct http { + long t_created; enum http_state state; char *url; CURL *curlh; @@ -62,6 +63,7 @@ http_get(struct http **ret, h->state = HS_ADD; h->cb = cb; h->cb_arg = arg; + h->t_created = btpd_seconds; if ((h->curlh = curl_easy_init()) == NULL) btpd_err("Fatal error in curl.\n"); @@ -88,6 +90,26 @@ http_get(struct http **ret, return 0; } +long +http_server_busy_time(const char *url, long s) +{ + struct http *h; + size_t len = strlen(url); + + pthread_mutex_lock(&m_httpq_lock); + h = BTPDQ_LAST(&m_httpq, http_tq); + while (h != NULL && + !((h->state == HS_ACTIVE || h->state == HS_ADD) && + strncmp(url, h->url, len) == 0)) + h = BTPDQ_PREV(h, http_tq, entry); + pthread_mutex_unlock(&m_httpq_lock); + + if (h == NULL || btpd_seconds - h->t_created >= s) + return 0; + else + return s - (btpd_seconds - h->t_created); +} + void http_cancel(struct http *http) { diff --git a/btpd/http.h b/btpd/http.h index 78861c6..8edaac4 100644 --- a/btpd/http.h +++ b/btpd/http.h @@ -24,6 +24,8 @@ int http_get(struct http **ret, void http_cancel(struct http *http); int http_succeeded(struct http_res *res); +long http_server_busy_time(const char *url, long s); + void http_init(void); #endif diff --git a/btpd/tracker_req.c b/btpd/tracker_req.c index 8945a11..e172a84 100644 --- a/btpd/tracker_req.c +++ b/btpd/tracker_req.c @@ -180,6 +180,7 @@ timer_cb(int fd, short type, void *arg) static void tr_send(struct torrent *tp, enum tr_event event) { + long busy_secs; char e_hash[61], e_id[61], qc;; const uint8_t *peer_id = btpd_get_peer_id(); @@ -187,6 +188,13 @@ tr_send(struct torrent *tp, enum tr_event event) tr->event = event; if (tr->ttype == TIMER_TIMEOUT) http_cancel(tr->req); + + if ((busy_secs = http_server_busy_time(tp->meta.announce, 3)) > 0) { + tr->ttype = TIMER_RETRY; + btpd_ev_add(&tr->timer, (& (struct timeval) { busy_secs, 0 })); + return; + } + tr->ttype = TIMER_TIMEOUT; btpd_ev_add(&tr->timer, REQ_TIMEOUT);