A clone of btpd with my configuration changes.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

260 Zeilen
5.4 KiB

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