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.

314 lignes
7.0 KiB

  1. #include "btpd.h"
  2. #include "http_client.h"
  3. #define REQ_DELAY 1
  4. #define DEFAULT_INTERVAL rand_between(25 * 60, 30 * 60)
  5. #define RETRY1_TIMEOUT (& (struct timespec) {240 + rand_between(0, 120), 0})
  6. #define RETRY2_TIMEOUT (& (struct timespec) {900 + rand_between(0, 300), 0})
  7. long tr_key;
  8. static long m_tlast_req, m_tnext_req;
  9. struct tr_entry {
  10. BTPDQ_ENTRY(tr_entry) entry;
  11. char *url;
  12. enum tr_type type;
  13. };
  14. BTPDQ_HEAD(tr_entry_tq, tr_entry);
  15. struct tr_tier {
  16. struct torrent *tp;
  17. struct tr_entry *cur;
  18. struct tr_entry_tq trackers;
  19. struct timeout timer;
  20. BTPDQ_ENTRY(tr_tier) entry;
  21. void *req;
  22. char *failure;
  23. int interval;
  24. int bad_conns;
  25. int active;
  26. int has_responded;
  27. enum tr_event event;
  28. };
  29. BTPDQ_HEAD(tr_tier_tq, tr_tier);
  30. struct trackers {
  31. struct tr_tier_tq trackers;
  32. };
  33. static void *
  34. req_send(struct tr_tier *t)
  35. {
  36. switch (t->cur->type) {
  37. case TR_HTTP:
  38. return httptr_req(t->tp, t, t->cur->url, t->event);
  39. default:
  40. abort();
  41. }
  42. }
  43. static void
  44. req_cancel(struct tr_tier *t)
  45. {
  46. switch (t->cur->type) {
  47. case TR_HTTP:
  48. httptr_cancel(t->req);
  49. break;
  50. default:
  51. abort();
  52. }
  53. t->req = NULL;
  54. }
  55. static void
  56. entry_send(struct tr_tier *t, struct tr_entry *e, enum tr_event event)
  57. {
  58. if (t->req != NULL)
  59. req_cancel(t);
  60. t->event = event;
  61. t->cur = e;
  62. if (m_tlast_req > btpd_seconds - REQ_DELAY) {
  63. m_tnext_req = max(m_tnext_req, m_tlast_req) + REQ_DELAY;
  64. btpd_timer_add(&t->timer,
  65. (& (struct timespec) { m_tnext_req - btpd_seconds, 0 }));
  66. return;
  67. }
  68. btpd_timer_del(&t->timer);
  69. if ((t->req = req_send(t)) == NULL) {
  70. asprintf(&t->failure, "failed to create tracker message to '%s' (%s).",
  71. e->url, strerror(errno));
  72. t->active = 0;
  73. return;
  74. }
  75. m_tlast_req = btpd_seconds;
  76. }
  77. static int
  78. tier_active(struct tr_tier *t)
  79. {
  80. return t->active;
  81. }
  82. static void
  83. tier_timer_cb(int fd, short type, void *arg)
  84. {
  85. struct tr_tier *t = arg;
  86. assert(tier_active(t));
  87. entry_send(t, BTPDQ_FIRST(&t->trackers), t->event);
  88. }
  89. static void
  90. tier_start(struct tr_tier *t)
  91. {
  92. assert(!tier_active(t) || t->event == TR_EV_STOPPED);
  93. if (t->failure != NULL) {
  94. free(t->failure);
  95. t->failure = NULL;
  96. }
  97. t->has_responded = 0;
  98. t->bad_conns = 0;
  99. t->active = 1;
  100. entry_send(t, BTPDQ_FIRST(&t->trackers), TR_EV_STARTED);
  101. }
  102. static void
  103. tier_stop(struct tr_tier *t)
  104. {
  105. if (!tier_active(t) || t->event == TR_EV_STOPPED)
  106. return;
  107. if (!t->has_responded && t->bad_conns > 1) {
  108. btpd_timer_del(&t->timer);
  109. if (t->req != NULL)
  110. req_cancel(t);
  111. t->active = 0;
  112. } else
  113. entry_send(t, BTPDQ_FIRST(&t->trackers), TR_EV_STOPPED);
  114. }
  115. static void
  116. tier_complete(struct tr_tier *t)
  117. {
  118. if (tier_active(t) && t->event == TR_EV_EMPTY)
  119. entry_send(t, BTPDQ_FIRST(&t->trackers), TR_EV_COMPLETED);
  120. }
  121. static void
  122. add_tracker(struct tr_tier *t, const char *url)
  123. {
  124. struct tr_entry *e;
  125. struct http_url *hu;
  126. if ((hu = http_url_parse(url)) != NULL) {
  127. http_url_free(hu);
  128. e = btpd_calloc(1, sizeof(*e));
  129. if ((e->url = strdup(url)) == NULL)
  130. btpd_err("Out of memory.\n");
  131. e->type = TR_HTTP;
  132. } else
  133. return;
  134. BTPDQ_INSERT_TAIL(&t->trackers, e, entry);
  135. }
  136. static struct tr_tier *
  137. tier_create(struct torrent *tp, struct mi_tier *tier)
  138. {
  139. struct tr_tier *t = btpd_calloc(1, sizeof(*t));
  140. BTPDQ_INIT(&t->trackers);
  141. for (int i = 0; i < tier->nurls; i++)
  142. add_tracker(t, tier->urls[i]);
  143. if (!BTPDQ_EMPTY(&t->trackers)) {
  144. t->tp = tp;
  145. t->interval = -1;
  146. t->event = TR_EV_STOPPED;
  147. timer_init(&t->timer, tier_timer_cb, t);
  148. return t;
  149. } else {
  150. free(t);
  151. return NULL;
  152. }
  153. }
  154. static void
  155. tier_kill(struct tr_tier *t)
  156. {
  157. struct tr_entry *e, *next;
  158. if (t->failure != NULL)
  159. free(t->failure);
  160. btpd_timer_del(&t->timer);
  161. if (t->req != NULL)
  162. req_cancel(t);
  163. BTPDQ_FOREACH_MUTABLE(e, &t->trackers, entry , next) {
  164. free(e->url);
  165. free(e);
  166. }
  167. free(t);
  168. }
  169. void
  170. tr_create(struct torrent *tp, const char *mi)
  171. {
  172. int i;
  173. struct tr_tier *t;
  174. struct mi_announce *ann;
  175. tp->tr = btpd_calloc(1, sizeof(*tp->tr));
  176. BTPDQ_INIT(&tp->tr->trackers);
  177. if ((ann = mi_announce(mi)) == NULL)
  178. btpd_err("Out of memory.\n");
  179. for (i = 0; i < ann->ntiers; i++)
  180. if ((t = tier_create(tp, &ann->tiers[i])) != NULL)
  181. BTPDQ_INSERT_TAIL(&tp->tr->trackers, t, entry);
  182. mi_free_announce(ann);
  183. }
  184. void
  185. tr_kill(struct torrent *tp)
  186. {
  187. struct tr_tier *t, *next;
  188. BTPDQ_FOREACH_MUTABLE(t, &tp->tr->trackers, entry, next)
  189. tier_kill(t);
  190. free(tp->tr);
  191. tp->tr = NULL;
  192. }
  193. void
  194. tr_start(struct torrent *tp)
  195. {
  196. struct tr_tier *t;
  197. BTPDQ_FOREACH(t, &tp->tr->trackers, entry)
  198. tier_start(t);
  199. }
  200. void
  201. tr_stop(struct torrent *tp)
  202. {
  203. struct tr_tier *t;
  204. BTPDQ_FOREACH(t, &tp->tr->trackers, entry)
  205. tier_stop(t);
  206. }
  207. void
  208. tr_complete(struct torrent *tp)
  209. {
  210. struct tr_tier *t;
  211. BTPDQ_FOREACH(t, &tp->tr->trackers, entry)
  212. tier_complete(t);
  213. }
  214. int
  215. tr_active(struct torrent *tp)
  216. {
  217. struct tr_tier *t;
  218. BTPDQ_FOREACH(t, &tp->tr->trackers, entry)
  219. if (tier_active(t))
  220. return 1;
  221. return 0;
  222. }
  223. int
  224. tr_good_count(struct torrent *tp)
  225. {
  226. int count = 0;
  227. struct tr_tier *t;
  228. BTPDQ_FOREACH(t, &tp->tr->trackers, entry)
  229. if (tier_active(t) && t->bad_conns == 0)
  230. count++;
  231. return count;
  232. }
  233. void
  234. tr_result(struct tr_tier *t, struct tr_response *res)
  235. {
  236. struct tr_entry *e;
  237. t->req = NULL;
  238. switch (res->type) {
  239. case TR_RES_FAIL:
  240. t->active = 0;
  241. t->failure = benc_str(res->mi_failure, NULL, NULL);
  242. btpd_log(BTPD_L_ERROR, "tracker at '%s' failed (%s).\n",
  243. t->cur->url, t->failure);
  244. break;
  245. case TR_RES_CONN:
  246. if ((e = BTPDQ_NEXT(t->cur, entry)) != NULL) {
  247. entry_send(t, e, t->event);
  248. break;
  249. }
  250. t->bad_conns++;
  251. if (t->event == TR_EV_STOPPED && t->bad_conns > 1)
  252. t->active = 0;
  253. else if (t->bad_conns == 1)
  254. entry_send(t, BTPDQ_FIRST(&t->trackers), t->event);
  255. else if (t->bad_conns == 2)
  256. btpd_timer_add(&t->timer, RETRY1_TIMEOUT);
  257. else
  258. btpd_timer_add(&t->timer, RETRY2_TIMEOUT);
  259. break;
  260. case TR_RES_BAD:
  261. case TR_RES_OK:
  262. if (t->event == TR_EV_STOPPED)
  263. t->active = 0;
  264. else {
  265. t->event = TR_EV_EMPTY;
  266. if (res->interval > 0)
  267. t->interval = res->interval;
  268. btpd_timer_add(&t->timer, (& (struct timespec) {
  269. t->interval > 0 ? t->interval : DEFAULT_INTERVAL, 0 }));
  270. }
  271. t->bad_conns = 0;
  272. t->has_responded = 1;
  273. BTPDQ_REMOVE(&t->trackers, t->cur, entry);
  274. BTPDQ_INSERT_HEAD(&t->trackers, t->cur, entry);
  275. break;
  276. default:
  277. abort();
  278. }
  279. }
  280. void
  281. tr_init(void)
  282. {
  283. tr_key = random();
  284. }