A clone of btpd with my configuration changes.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

230 рядки
5.2 KiB

  1. #include <sys/types.h>
  2. #include <sys/mman.h>
  3. #include <sys/stat.h>
  4. #include <assert.h>
  5. #include <errno.h>
  6. #include <fcntl.h>
  7. #include <math.h>
  8. #include <limits.h>
  9. #include <stdarg.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <openssl/sha.h>
  15. #include "btpd.h"
  16. #include "tracker_req.h"
  17. #include "stream.h"
  18. static unsigned m_ntorrents;
  19. static struct torrent_tq m_torrents = BTPDQ_HEAD_INITIALIZER(m_torrents);
  20. const struct torrent_tq *
  21. torrent_get_all(void)
  22. {
  23. return &m_torrents;
  24. }
  25. unsigned
  26. torrent_count(void)
  27. {
  28. return m_ntorrents;
  29. }
  30. struct torrent *
  31. torrent_by_num(unsigned num)
  32. {
  33. struct tlib *tl = tlib_by_num(num);
  34. return tl != NULL ? tl->tp : NULL;
  35. }
  36. struct torrent *
  37. torrent_by_hash(const uint8_t *hash)
  38. {
  39. struct tlib *tl = tlib_by_hash(hash);
  40. return tl != NULL ? tl->tp : NULL;
  41. }
  42. const char *
  43. torrent_name(struct torrent *tp)
  44. {
  45. return tp->tl->name;
  46. }
  47. off_t
  48. torrent_piece_size(struct torrent *tp, uint32_t index)
  49. {
  50. if (index < tp->npieces - 1)
  51. return tp->piece_length;
  52. else {
  53. off_t allbutlast = tp->piece_length * (tp->npieces - 1);
  54. return tp->total_length - allbutlast;
  55. }
  56. }
  57. uint32_t
  58. torrent_piece_blocks(struct torrent *tp, uint32_t piece)
  59. {
  60. return ceil(torrent_piece_size(tp, piece) / (double)PIECE_BLOCKLEN);
  61. }
  62. uint32_t
  63. torrent_block_size(struct torrent *tp, uint32_t piece, uint32_t nblocks,
  64. uint32_t block)
  65. {
  66. if (block < nblocks - 1)
  67. return PIECE_BLOCKLEN;
  68. else {
  69. uint32_t allbutlast = PIECE_BLOCKLEN * (nblocks - 1);
  70. return torrent_piece_size(tp, piece) - allbutlast;
  71. }
  72. }
  73. enum ipc_err
  74. torrent_start(struct tlib *tl)
  75. {
  76. struct stat sb;
  77. struct torrent *tp;
  78. char *mi;
  79. char relpath[RELPATH_SIZE];
  80. char file[PATH_MAX];
  81. if (tl->dir == NULL)
  82. return IPC_EBADTENT;
  83. if (stat(tl->dir, &sb) == 0) {
  84. if ((sb.st_mode & S_IFMT) != S_IFDIR) {
  85. btpd_log(BTPD_L_ERROR,
  86. "torrent '%s': content dir '%s' is not a directory\n",
  87. tl->name, tl->dir);
  88. return IPC_EBADCDIR;
  89. }
  90. } else if (errno == ENOENT) {
  91. if (mkdirs(tl->dir, 0777) != 0 && errno != EEXIST) {
  92. btpd_log(BTPD_L_ERROR, "torrent '%s': "
  93. "failed to create content dir '%s' (%s).\n",
  94. tl->name, tl->dir, strerror(errno));
  95. return IPC_ECREATECDIR;
  96. }
  97. } else {
  98. btpd_log(BTPD_L_ERROR,
  99. "torrent '%s': couldn't stat content dir '%s' (%s)\n",
  100. tl->name, tl->dir, strerror(errno));
  101. return IPC_EBADCDIR;
  102. }
  103. bin2hex(tl->hash, relpath, 20);
  104. snprintf(file, PATH_MAX, "torrents/%s/torrent", relpath);
  105. if ((mi = mi_load(file, NULL)) == NULL) {
  106. btpd_log(BTPD_L_ERROR,
  107. "torrent '%s': failed to load metainfo (%s).\n",
  108. tl->name, strerror(errno));
  109. return IPC_EBADTENT;
  110. }
  111. tp = btpd_calloc(1, sizeof(*tp));
  112. tp->tl = tl;
  113. bcopy(relpath, tp->relpath, RELPATH_SIZE);
  114. tp->files = mi_files(mi);
  115. tp->nfiles = mi_nfiles(mi);
  116. if (tp->files == NULL)
  117. btpd_err("out of memory.\n");
  118. tp->total_length = mi_total_length(mi);
  119. tp->piece_length = mi_piece_length(mi);
  120. tp->npieces = mi_npieces(mi);
  121. tp->pieces_off =
  122. benc_dget_mem(benc_dget_dct(mi, "info"), "pieces", NULL) - mi;
  123. btpd_log(BTPD_L_BTPD, "Starting torrent '%s'.\n", torrent_name(tp));
  124. if (tr_create(tp, mi) == 0) {
  125. net_create(tp);
  126. cm_create(tp);
  127. BTPDQ_INSERT_TAIL(&m_torrents, tp, entry);
  128. m_ntorrents++;
  129. cm_start(tp);
  130. tl->tp = tp;
  131. free(mi);
  132. return IPC_OK;
  133. } else {
  134. mi_free_files(tp->nfiles, tp->files);
  135. free(tp);
  136. free(mi);
  137. return IPC_EBADTRACKER;
  138. }
  139. }
  140. static void
  141. torrent_kill(struct torrent *tp)
  142. {
  143. btpd_log(BTPD_L_BTPD, "Stopped torrent '%s'.\n", torrent_name(tp));
  144. assert(m_ntorrents > 0);
  145. assert(!(tr_active(tp) || net_active(tp) || cm_active(tp)));
  146. m_ntorrents--;
  147. BTPDQ_REMOVE(&m_torrents, tp, entry);
  148. if (!tp->delete)
  149. tlib_update_info(tp->tl);
  150. tp->tl->tp = NULL;
  151. if (tp->delete)
  152. tlib_del(tp->tl);
  153. tr_kill(tp);
  154. net_kill(tp);
  155. cm_kill(tp);
  156. mi_free_files(tp->nfiles, tp->files);
  157. free(tp);
  158. if (m_ntorrents == 0)
  159. btpd_on_no_torrents();
  160. }
  161. void
  162. torrent_stop(struct torrent *tp)
  163. {
  164. int tra, cma;
  165. switch (tp->state) {
  166. case T_ACTIVE:
  167. case T_STARTING:
  168. tp->state = T_STOPPING;
  169. if (net_active(tp))
  170. net_stop(tp);
  171. tra = tr_active(tp);
  172. cma = cm_active(tp);
  173. if (tra)
  174. tr_stop(tp);
  175. if (cma)
  176. cm_stop(tp);
  177. if (!(tra || cma))
  178. torrent_kill(tp);
  179. break;
  180. case T_STOPPING:
  181. if (tr_active(tp))
  182. tr_stop(tp);
  183. break;
  184. }
  185. }
  186. void
  187. torrent_on_cm_started(struct torrent *tp)
  188. {
  189. tp->state = T_ACTIVE;
  190. net_start(tp);
  191. tr_start(tp);
  192. }
  193. void
  194. torrent_on_cm_stopped(struct torrent *tp)
  195. {
  196. assert(tp->state == T_STOPPING);
  197. if (!tr_active(tp))
  198. torrent_kill(tp);
  199. }
  200. void
  201. torrent_on_tr_stopped(struct torrent *tp)
  202. {
  203. assert(tp->state == T_STOPPING);
  204. if (!cm_active(tp))
  205. torrent_kill(tp);
  206. }