A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
4.6 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_get(const uint8_t *hash)
  32. {
  33. struct torrent *tp = BTPDQ_FIRST(&m_torrents);
  34. while (tp != NULL && bcmp(hash, tp->meta.info_hash, 20) != 0)
  35. tp = BTPDQ_NEXT(tp, entry);
  36. return tp;
  37. }
  38. const char *
  39. torrent_name(struct torrent *tp)
  40. {
  41. return tp->meta.name;
  42. }
  43. off_t
  44. torrent_piece_size(struct torrent *tp, uint32_t index)
  45. {
  46. if (index < tp->meta.npieces - 1)
  47. return tp->meta.piece_length;
  48. else {
  49. off_t allbutlast = tp->meta.piece_length * (tp->meta.npieces - 1);
  50. return tp->meta.total_length - allbutlast;
  51. }
  52. }
  53. uint32_t
  54. torrent_piece_blocks(struct torrent *tp, uint32_t piece)
  55. {
  56. return ceil(torrent_piece_size(tp, piece) / (double)PIECE_BLOCKLEN);
  57. }
  58. uint32_t
  59. torrent_block_size(struct torrent *tp, uint32_t piece, uint32_t nblocks,
  60. uint32_t block)
  61. {
  62. if (block < nblocks - 1)
  63. return PIECE_BLOCKLEN;
  64. else {
  65. uint32_t allbutlast = PIECE_BLOCKLEN * (nblocks - 1);
  66. return torrent_piece_size(tp, piece) - allbutlast;
  67. }
  68. }
  69. static void
  70. torrent_relpath(const uint8_t *hash, char *buf)
  71. {
  72. for (int i = 0; i < 20; i++)
  73. snprintf(buf + i * 2, 3, "%.2x", hash[i]);
  74. }
  75. int
  76. torrent_set_links(const uint8_t *hash, const char *torrent,
  77. const char *content)
  78. {
  79. char relpath[RELPATH_SIZE];
  80. char file[PATH_MAX];
  81. torrent_relpath(hash, relpath);
  82. snprintf(file, PATH_MAX, "torrents/%s", relpath);
  83. if (mkdir(file, 0777) == -1 && errno != EEXIST)
  84. return errno;
  85. snprintf(file, PATH_MAX, "torrents/%s/torrent", relpath);
  86. if (unlink(file) == -1 && errno != ENOENT)
  87. return errno;
  88. if (symlink(torrent, file) == -1)
  89. return errno;
  90. snprintf(file, PATH_MAX, "torrents/%s/content", relpath);
  91. if (unlink(file) == -1 && errno != ENOENT)
  92. return errno;
  93. if (symlink(content, file) == -1)
  94. return errno;
  95. return 0;
  96. }
  97. int
  98. torrent_start(const uint8_t *hash)
  99. {
  100. struct torrent *tp;
  101. struct metainfo *mi;
  102. int error;
  103. char relpath[RELPATH_SIZE];
  104. char file[PATH_MAX];
  105. torrent_relpath(hash, relpath);
  106. snprintf(file, PATH_MAX, "torrents/%s/torrent", relpath);
  107. if ((error = load_metainfo(file, -1, 0, &mi)) != 0) {
  108. btpd_log(BTPD_L_ERROR, "Couldn't load torrent file %s: %s.\n",
  109. file, strerror(error));
  110. return error;
  111. }
  112. tp = btpd_calloc(1, sizeof(*tp));
  113. bcopy(relpath, tp->relpath, RELPATH_SIZE);
  114. tp->meta = *mi;
  115. free(mi);
  116. btpd_log(BTPD_L_BTPD, "Starting torrent '%s'.\n", torrent_name(tp));
  117. if ((error = tr_create(tp)) == 0) {
  118. net_create(tp);
  119. cm_create(tp);
  120. BTPDQ_INSERT_TAIL(&m_torrents, tp, entry);
  121. m_ntorrents++;
  122. cm_start(tp);
  123. } else {
  124. clear_metainfo(&tp->meta);
  125. free(tp);
  126. }
  127. return error;
  128. }
  129. static void
  130. torrent_kill(struct torrent *tp)
  131. {
  132. btpd_log(BTPD_L_BTPD, "Removed torrent '%s'.\n", torrent_name(tp));
  133. assert(m_ntorrents > 0);
  134. assert(!(tr_active(tp) || net_active(tp) || cm_active(tp)));
  135. m_ntorrents--;
  136. BTPDQ_REMOVE(&m_torrents, tp, entry);
  137. clear_metainfo(&tp->meta);
  138. tr_kill(tp);
  139. net_kill(tp);
  140. cm_kill(tp);
  141. free(tp);
  142. if (m_ntorrents == 0)
  143. btpd_on_no_torrents();
  144. }
  145. void
  146. torrent_stop(struct torrent *tp)
  147. {
  148. int tra, cma;
  149. switch (tp->state) {
  150. case T_STARTING:
  151. case T_ACTIVE:
  152. tp->state = T_STOPPING;
  153. if (net_active(tp))
  154. net_stop(tp);
  155. tra = tr_active(tp);
  156. cma = cm_active(tp);
  157. if (tra)
  158. tr_stop(tp);
  159. if (cma)
  160. cm_stop(tp);
  161. if (!(tra || cma))
  162. torrent_kill(tp);
  163. break;
  164. case T_STOPPING:
  165. if (tr_active(tp))
  166. tr_stop(tp);
  167. break;
  168. }
  169. }
  170. void
  171. torrent_on_cm_started(struct torrent *tp)
  172. {
  173. tp->state = T_ACTIVE;
  174. net_start(tp);
  175. tr_start(tp);
  176. }
  177. void
  178. torrent_on_cm_stopped(struct torrent *tp)
  179. {
  180. assert(tp->state == T_STOPPING);
  181. if (!tr_active(tp))
  182. torrent_kill(tp);
  183. }
  184. void
  185. torrent_on_tr_stopped(struct torrent *tp)
  186. {
  187. assert(tp->state == T_STOPPING);
  188. if (!cm_active(tp))
  189. torrent_kill(tp);
  190. }