A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

256 lignes
5.3 KiB

  1. #include "btpd.h"
  2. #define REQ_DELAY 1
  3. #define STOP_ERRORS 5
  4. #define REQ_TIMEOUT (& (struct timeval) { 120, 0 })
  5. #define RETRY_WAIT (& (struct timeval) { rand_between(35, 70), 0 })
  6. long tr_key;
  7. static long m_tlast_req, m_tnext_req;
  8. enum timer_type {
  9. TIMER_NONE,
  10. TIMER_TIMEOUT,
  11. TIMER_INTERVAL,
  12. TIMER_RETRY
  13. };
  14. struct tracker {
  15. enum timer_type ttype;
  16. enum tr_event event;
  17. int interval;
  18. unsigned nerrors;
  19. int tier, url;
  20. struct mi_announce *ann;
  21. void *req;
  22. struct event timer;
  23. };
  24. typedef struct _dummy *(*request_fun_t)(struct torrent *, enum tr_event,
  25. const char *);
  26. typedef void (*cancel_fun_t)(struct _dummy *);
  27. struct tr_op {
  28. int len;
  29. const char *scheme;
  30. request_fun_t request;
  31. cancel_fun_t cancel;
  32. };
  33. static struct tr_op m_http_op = {
  34. 7, "http://", (request_fun_t)http_tr_req, (cancel_fun_t)http_tr_cancel
  35. };
  36. static struct tr_op *m_tr_ops[] = {
  37. &m_http_op, NULL
  38. };
  39. static char *
  40. get_url(struct tracker *tr)
  41. {
  42. return tr->ann->tiers[tr->tier].urls[tr->url];
  43. }
  44. static void
  45. good_url(struct tracker *tr)
  46. {
  47. char *set = tr->ann->tiers[tr->tier].urls[tr->url], *hold;
  48. for (int i = 0; i <= tr->url; i++) {
  49. hold = tr->ann->tiers[tr->tier].urls[i];
  50. tr->ann->tiers[tr->tier].urls[i] = set;
  51. set = hold;
  52. }
  53. tr->tier = 0;
  54. tr->url = 0;
  55. }
  56. static void
  57. next_url(struct tracker *tr)
  58. {
  59. tr->url = (tr->url + 1) % tr->ann->tiers[tr->tier].nurls;
  60. if (tr->url == 0)
  61. tr->tier = (tr->tier + 1) % tr->ann->ntiers;
  62. }
  63. struct tr_op *
  64. get_op(struct tracker *tr)
  65. {
  66. struct tr_op **opp;
  67. char *url = get_url(tr);
  68. for (opp = m_tr_ops; *opp != NULL; opp++)
  69. if (strncasecmp((*opp)->scheme, url, (*opp)->len) == 0)
  70. return *opp;
  71. return NULL;
  72. }
  73. static void
  74. tr_cancel(struct tracker *tr)
  75. {
  76. struct tr_op *op = get_op(tr);
  77. assert(op != NULL);
  78. op->cancel(tr->req);
  79. tr->req = NULL;
  80. }
  81. static void
  82. tr_set_stopped(struct torrent *tp)
  83. {
  84. struct tracker *tr = tp->tr;
  85. btpd_ev_del(&tr->timer);
  86. tr->ttype = TIMER_NONE;
  87. if (tr->req != NULL)
  88. tr_cancel(tr);
  89. }
  90. static void
  91. tr_send(struct torrent *tp, enum tr_event event)
  92. {
  93. struct tracker *tr = tp->tr;
  94. struct tr_op *op = get_op(tr);
  95. tr->event = event;
  96. if (tr->req != NULL)
  97. tr_cancel(tr);
  98. if (m_tlast_req > btpd_seconds - REQ_DELAY) {
  99. m_tnext_req = max(m_tnext_req, m_tlast_req) + REQ_DELAY;
  100. tr->ttype = TIMER_RETRY;
  101. btpd_ev_add(&tr->timer,
  102. (& (struct timeval) { m_tnext_req - btpd_seconds, 0 }));
  103. return;
  104. }
  105. if ((op == NULL ||
  106. (tr->req = op->request(tp, event, get_url(tr))) == NULL)) {
  107. tr->nerrors++;
  108. if (tr->event == TR_EV_STOPPED && tr->nerrors >= STOP_ERRORS) {
  109. tr_set_stopped(tp);
  110. return;
  111. }
  112. next_url(tr);
  113. tr->ttype = TIMER_RETRY;
  114. btpd_ev_add(&tr->timer, (& (struct timeval) { 5, 0 }));
  115. } else {
  116. m_tlast_req = btpd_seconds;
  117. tr->ttype = TIMER_TIMEOUT;
  118. btpd_ev_add(&tr->timer, REQ_TIMEOUT);
  119. }
  120. }
  121. void
  122. tr_result(struct torrent *tp, enum tr_res res, int interval)
  123. {
  124. struct tracker *tr = tp->tr;
  125. tr->req = NULL;
  126. if (tr->event == TR_EV_STOPPED &&
  127. (res == TR_RES_OK || tr->nerrors >= STOP_ERRORS - 1))
  128. tr_set_stopped(tp);
  129. else if (res == TR_RES_OK) {
  130. good_url(tr);
  131. tr->interval = interval;
  132. tr->nerrors = 0;
  133. tr->ttype = TIMER_INTERVAL;
  134. btpd_ev_add(&tr->timer, (& (struct timeval) { tr->interval, 0}));
  135. } else {
  136. tr->nerrors++;
  137. tr->ttype = TIMER_RETRY;
  138. btpd_ev_add(&tr->timer, RETRY_WAIT);
  139. next_url(tr);
  140. }
  141. }
  142. static void
  143. timer_cb(int fd, short type, void *arg)
  144. {
  145. struct torrent *tp = arg;
  146. struct tracker *tr = tp->tr;
  147. switch (tr->ttype) {
  148. case TIMER_TIMEOUT:
  149. btpd_log(BTPD_L_ERROR, "Tracker request timed out for '%s'.\n",
  150. torrent_name(tp));
  151. tr->nerrors++;
  152. if (tr->event == TR_EV_STOPPED && tr->nerrors >= STOP_ERRORS) {
  153. tr_set_stopped(tp);
  154. break;
  155. }
  156. tr_cancel(tr);
  157. next_url(tr);
  158. case TIMER_RETRY:
  159. tr_send(tp, tr->event);
  160. break;
  161. case TIMER_INTERVAL:
  162. tr_send(tp, TR_EV_EMPTY);
  163. break;
  164. default:
  165. abort();
  166. }
  167. }
  168. int
  169. tr_create(struct torrent *tp, const char *mi)
  170. {
  171. tp->tr = btpd_calloc(1, sizeof(*tp->tr));
  172. if ((tp->tr->ann = mi_announce(mi)) == NULL)
  173. btpd_err("Out of memory.\n");
  174. evtimer_set(&tp->tr->timer, timer_cb, tp);
  175. return 0;
  176. }
  177. void
  178. tr_kill(struct torrent *tp)
  179. {
  180. struct tracker *tr = tp->tr;
  181. tp->tr = NULL;
  182. btpd_ev_del(&tr->timer);
  183. if (tr->req != NULL)
  184. tr_cancel(tr);
  185. mi_free_announce(tr->ann);
  186. free(tr);
  187. }
  188. void
  189. tr_start(struct torrent *tp)
  190. {
  191. tr_send(tp, TR_EV_STARTED);
  192. }
  193. void
  194. tr_refresh(struct torrent *tp)
  195. {
  196. tr_send(tp, TR_EV_EMPTY);
  197. }
  198. void
  199. tr_complete(struct torrent *tp)
  200. {
  201. tr_send(tp, TR_EV_COMPLETED);
  202. }
  203. void
  204. tr_stop(struct torrent *tp)
  205. {
  206. if (tp->tr->event == TR_EV_STOPPED)
  207. tr_set_stopped(tp);
  208. else
  209. tr_send(tp, TR_EV_STOPPED);
  210. }
  211. int
  212. tr_active(struct torrent *tp)
  213. {
  214. return tp->tr->ttype != TIMER_NONE;
  215. }
  216. unsigned
  217. tr_errors(struct torrent *tp)
  218. {
  219. return tp->tr->nerrors;
  220. }
  221. void
  222. tr_init(void)
  223. {
  224. tr_key = random();
  225. }