A clone of btpd with my configuration changes.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

216 行
5.0 KiB

  1. #include "btpd.h"
  2. #include <openssl/sha.h>
  3. #define SAVE_INTERVAL 300
  4. static unsigned m_ntorrents;
  5. static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);
  6. static unsigned m_tsave;
  7. static struct torrent *m_savetp;
  8. const struct torrent_tq *
  9. torrent_get_all(void)
  10. {
  11. return &m_torrents;
  12. }
  13. unsigned
  14. torrent_count(void)
  15. {
  16. return m_ntorrents;
  17. }
  18. struct torrent *
  19. torrent_by_num(unsigned num)
  20. {
  21. struct tlib *tl = tlib_by_num(num);
  22. return tl != NULL ? tl->tp : NULL;
  23. }
  24. struct torrent *
  25. torrent_by_hash(const uint8_t *hash)
  26. {
  27. struct tlib *tl = tlib_by_hash(hash);
  28. return tl != NULL ? tl->tp : NULL;
  29. }
  30. const char *
  31. torrent_name(struct torrent *tp)
  32. {
  33. return tp->tl->name;
  34. }
  35. off_t
  36. torrent_piece_size(struct torrent *tp, uint32_t index)
  37. {
  38. if (index < tp->npieces - 1)
  39. return tp->piece_length;
  40. else {
  41. off_t allbutlast = tp->piece_length * (tp->npieces - 1);
  42. return tp->total_length - allbutlast;
  43. }
  44. }
  45. uint32_t
  46. torrent_piece_blocks(struct torrent *tp, uint32_t piece)
  47. {
  48. return ceil(torrent_piece_size(tp, piece) / (double)PIECE_BLOCKLEN);
  49. }
  50. uint32_t
  51. torrent_block_size(struct torrent *tp, uint32_t piece, uint32_t nblocks,
  52. uint32_t block)
  53. {
  54. if (block < nblocks - 1)
  55. return PIECE_BLOCKLEN;
  56. else {
  57. uint32_t allbutlast = PIECE_BLOCKLEN * (nblocks - 1);
  58. return torrent_piece_size(tp, piece) - allbutlast;
  59. }
  60. }
  61. enum ipc_err
  62. torrent_start(struct tlib *tl)
  63. {
  64. struct torrent *tp;
  65. char *mi;
  66. if (tl->dir == NULL)
  67. return IPC_EBADTENT;
  68. if (tlib_load_mi(tl, &mi) != 0)
  69. return IPC_EBADTENT;
  70. tp = btpd_calloc(1, sizeof(*tp));
  71. tp->tl = tl;
  72. tp->files = mi_files(mi);
  73. tp->nfiles = mi_nfiles(mi);
  74. if (tp->files == NULL)
  75. btpd_err("out of memory.\n");
  76. tp->total_length = mi_total_length(mi);
  77. tp->piece_length = mi_piece_length(mi);
  78. tp->npieces = mi_npieces(mi);
  79. tp->pieces_off =
  80. benc_dget_mem(benc_dget_dct(mi, "info"), "pieces", NULL) - mi;
  81. btpd_log(BTPD_L_BTPD, "Starting torrent '%s'.\n", torrent_name(tp));
  82. tr_create(tp, mi);
  83. tl->tp = tp;
  84. net_create(tp);
  85. cm_create(tp, mi);
  86. BTPDQ_INSERT_TAIL(&m_torrents, tp, entry);
  87. m_ntorrents++;
  88. cm_start(tp, 0);
  89. free(mi);
  90. if (m_ntorrents == 1) {
  91. m_tsave = btpd_seconds + SAVE_INTERVAL;
  92. m_savetp = tp;
  93. }
  94. return IPC_OK;
  95. }
  96. static void
  97. torrent_kill(struct torrent *tp)
  98. {
  99. btpd_log(BTPD_L_BTPD, "Stopped torrent '%s'.\n", torrent_name(tp));
  100. assert(m_ntorrents > 0);
  101. assert(!(tr_active(tp) || net_active(tp) || cm_active(tp)));
  102. m_ntorrents--;
  103. BTPDQ_REMOVE(&m_torrents, tp, entry);
  104. tp->tl->tp = NULL;
  105. if (tp->delete)
  106. tlib_del(tp->tl);
  107. tr_kill(tp);
  108. net_kill(tp);
  109. cm_kill(tp);
  110. mi_free_files(tp->nfiles, tp->files);
  111. if (m_savetp == tp)
  112. if ((m_savetp = BTPDQ_NEXT(tp, entry)) == NULL)
  113. m_savetp = BTPDQ_FIRST(&m_torrents);
  114. free(tp);
  115. }
  116. void
  117. torrent_stop(struct torrent *tp, int delete)
  118. {
  119. if (delete)
  120. tp->delete = 1;
  121. switch (tp->state) {
  122. case T_LEECH:
  123. case T_SEED:
  124. case T_STARTING:
  125. tp->state = T_STOPPING;
  126. if (net_active(tp))
  127. net_stop(tp);
  128. if (tr_active(tp))
  129. tr_stop(tp);
  130. if (cm_active(tp))
  131. cm_stop(tp);
  132. if (!delete)
  133. tlib_update_info(tp->tl, 0);
  134. break;
  135. case T_STOPPING:
  136. break;
  137. }
  138. }
  139. void
  140. torrent_on_tick(struct torrent *tp)
  141. {
  142. if (tp->state != T_STOPPING && cm_error(tp))
  143. torrent_stop(tp, 0);
  144. switch (tp->state) {
  145. case T_STARTING:
  146. if (cm_started(tp)) {
  147. if (cm_full(tp))
  148. tp->state = T_SEED;
  149. else
  150. tp->state = T_LEECH;
  151. net_start(tp);
  152. tr_start(tp);
  153. }
  154. break;
  155. case T_LEECH:
  156. if (cm_full(tp)) {
  157. struct peer *p, *next;
  158. tp->state = T_SEED;
  159. btpd_log(BTPD_L_BTPD, "Finished downloading '%s'.\n",
  160. torrent_name(tp));
  161. tr_complete(tp);
  162. BTPDQ_FOREACH_MUTABLE(p, &tp->net->peers, p_entry, next) {
  163. assert(p->nwant == 0);
  164. if (peer_full(p))
  165. peer_kill(p);
  166. }
  167. }
  168. break;
  169. case T_STOPPING:
  170. if (!(cm_active(tp) || tr_active(tp)))
  171. torrent_kill(tp);
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. void
  178. torrent_on_tick_all(void)
  179. {
  180. struct torrent *tp, *next;
  181. BTPDQ_FOREACH_MUTABLE(tp, &m_torrents, entry, next)
  182. torrent_on_tick(tp);
  183. if (m_savetp != NULL && m_tsave <= btpd_seconds) {
  184. if (m_savetp->state == T_LEECH || m_savetp->state == T_SEED) {
  185. tlib_update_info(m_savetp->tl, 1);
  186. if ((m_savetp = BTPDQ_NEXT(m_savetp, entry)) == NULL)
  187. m_savetp = BTPDQ_FIRST(&m_torrents);
  188. if (m_ntorrents > 0)
  189. m_tsave = btpd_seconds +
  190. max(m_ntorrents, SAVE_INTERVAL) / m_ntorrents;
  191. }
  192. }
  193. }