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.

272 lines
6.0 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 int
  19. ro_fd_cb(const char *path, int *fd, void *arg)
  20. {
  21. struct torrent *tp = arg;
  22. return vopen(fd, O_RDONLY, "%s/content/%s", tp->relpath, path);
  23. }
  24. static int
  25. wo_fd_cb(const char *path, int *fd, void *arg)
  26. {
  27. struct torrent *tp = arg;
  28. return vopen(fd, O_WRONLY|O_CREAT, "%s/content/%s", tp->relpath, path);
  29. }
  30. static int
  31. torrent_load3(const char *file, struct metainfo *mi, char *mem, size_t memsiz)
  32. {
  33. struct torrent *tp = btpd_calloc(1, sizeof(*tp));
  34. tp->relpath = strdup(file);
  35. if (tp->relpath == NULL)
  36. btpd_err("Out of memory.\n");
  37. tp->piece_count = btpd_calloc(mi->npieces, sizeof(tp->piece_count[0]));
  38. tp->busy_field = btpd_calloc(ceil(mi->npieces / 8.0), 1);
  39. BTPDQ_INIT(&tp->peers);
  40. BTPDQ_INIT(&tp->getlst);
  41. tp->imem = mem;
  42. tp->isiz = memsiz;
  43. tp->piece_field = tp->imem;
  44. tp->block_field =
  45. (uint8_t *)tp->imem + (size_t)ceil(mi->npieces / 8.0);
  46. for (uint32_t i = 0; i < mi->npieces; i++)
  47. if (has_bit(tp->piece_field, i))
  48. tp->have_npieces++;
  49. tp->meta = *mi;
  50. free(mi);
  51. btpd_add_torrent(tp);
  52. tracker_req(tp, TR_STARTED);
  53. return 0;
  54. }
  55. static int
  56. torrent_load2(const char *name, struct metainfo *mi)
  57. {
  58. int error, ifd;
  59. struct stat sb;
  60. char *mem;
  61. size_t memsiz;
  62. const char *file = name;
  63. if ((error = vopen(&ifd, O_RDWR, "%s/resume", file)) != 0) {
  64. btpd_log(BTPD_L_ERROR, "Error opening %s.i: %s.\n",
  65. file, strerror(error));
  66. return error;
  67. }
  68. if (fstat(ifd, &sb) == -1) {
  69. error = errno;
  70. btpd_log(BTPD_L_ERROR, "Error stating %s.i: %s.\n",
  71. file, strerror(error));
  72. close(ifd);
  73. return error;
  74. }
  75. memsiz =
  76. ceil(mi->npieces / 8.0) +
  77. mi->npieces * ceil(mi->piece_length / (double)(1 << 17));
  78. if (sb.st_size != memsiz) {
  79. btpd_log(BTPD_L_ERROR, "File has wrong size: %s.i.\n", file);
  80. close(ifd);
  81. return EINVAL;
  82. }
  83. mem = mmap(NULL, memsiz, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
  84. if (mem == MAP_FAILED)
  85. btpd_err("Error mmap'ing %s.i: %s.\n", file, strerror(errno));
  86. close(ifd);
  87. if ((error = torrent_load3(file, mi, mem, memsiz) != 0)) {
  88. munmap(mem, memsiz);
  89. return error;
  90. }
  91. return 0;
  92. }
  93. int
  94. torrent_load(const char *name)
  95. {
  96. struct metainfo *mi;
  97. int error;
  98. char file[PATH_MAX];
  99. snprintf(file, PATH_MAX, "%s/torrent", name);
  100. if ((error = load_metainfo(file, -1, 0, &mi)) != 0) {
  101. btpd_log(BTPD_L_ERROR, "Couldn't load metainfo file %s: %s.\n",
  102. file, strerror(error));
  103. return error;
  104. }
  105. if (btpd_get_torrent(mi->info_hash) != NULL) {
  106. btpd_log(BTPD_L_BTPD, "%s has same hash as an already loaded torrent.\n", file);
  107. error = EEXIST;
  108. }
  109. if (error == 0)
  110. error = torrent_load2(name, mi);
  111. if (error != 0) {
  112. clear_metainfo(mi);
  113. free(mi);
  114. }
  115. return error;
  116. }
  117. void
  118. torrent_unload(struct torrent *tp)
  119. {
  120. struct peer *peer;
  121. struct piece *piece;
  122. btpd_log(BTPD_L_BTPD, "Unloading %s.\n", tp->relpath);
  123. tracker_req(tp, TR_STOPPED);
  124. peer = BTPDQ_FIRST(&tp->peers);
  125. while (peer != NULL) {
  126. struct peer *next = BTPDQ_NEXT(peer, p_entry);
  127. BTPDQ_REMOVE(&tp->peers, peer, p_entry);
  128. BTPDQ_INSERT_TAIL(&net_unattached, peer, p_entry);
  129. peer->flags &= ~PF_ATTACHED;
  130. peer = next;
  131. }
  132. peer = BTPDQ_FIRST(&net_unattached);
  133. while (peer != NULL) {
  134. struct peer *next = BTPDQ_NEXT(peer, p_entry);
  135. if (peer->tp == tp)
  136. peer_kill(peer);
  137. peer = next;
  138. }
  139. while ((piece = BTPDQ_FIRST(&tp->getlst)) != NULL)
  140. piece_free(piece);
  141. free(tp->piece_count);
  142. free(tp->busy_field);
  143. free((void *)tp->relpath);
  144. clear_metainfo(&tp->meta);
  145. munmap(tp->imem, tp->isiz);
  146. btpd_del_torrent(tp);
  147. free(tp);
  148. }
  149. off_t
  150. torrent_bytes_left(struct torrent *tp)
  151. {
  152. if (tp->have_npieces == 0)
  153. return tp->meta.total_length;
  154. else if (has_bit(tp->piece_field, tp->meta.npieces - 1)) {
  155. return tp->meta.total_length -
  156. ((tp->have_npieces - 1) * tp->meta.piece_length +
  157. tp->meta.total_length % tp->meta.piece_length);
  158. } else
  159. return tp->meta.total_length -
  160. tp->have_npieces * tp->meta.piece_length;
  161. }
  162. char *
  163. torrent_get_bytes(struct torrent *tp, off_t start, size_t len)
  164. {
  165. char *buf = btpd_malloc(len);
  166. struct bt_stream_ro *bts;
  167. if ((bts = bts_open_ro(&tp->meta, start, ro_fd_cb, tp)) == NULL)
  168. btpd_err("Out of memory.\n");
  169. if (bts_read_ro(bts, buf, len) != 0)
  170. btpd_err("Io error.\n");
  171. bts_close_ro(bts);
  172. return buf;
  173. }
  174. void
  175. torrent_put_bytes(struct torrent *tp, const char *buf, off_t start, size_t len)
  176. {
  177. int err;
  178. struct bt_stream_wo *bts;
  179. if ((bts = bts_open_wo(&tp->meta, start, wo_fd_cb, tp)) == NULL)
  180. btpd_err("Out of memory.\n");
  181. if ((err = bts_write_wo(bts, buf, len)) != 0)
  182. btpd_err("Io error1: %s\n", strerror(err));
  183. if ((err = bts_close_wo(bts)) != 0)
  184. btpd_err("Io error2: %s\n", strerror(err));
  185. }
  186. int
  187. torrent_has_peer(struct torrent *tp, const uint8_t *id)
  188. {
  189. int has = 0;
  190. struct peer *p = BTPDQ_FIRST(&tp->peers);
  191. while (p != NULL) {
  192. if (bcmp(p->id, id, 20) == 0) {
  193. has = 1;
  194. break;
  195. }
  196. p = BTPDQ_NEXT(p, p_entry);
  197. }
  198. return has;
  199. }
  200. off_t
  201. torrent_piece_size(struct torrent *tp, uint32_t index)
  202. {
  203. if (index < tp->meta.npieces - 1)
  204. return tp->meta.piece_length;
  205. else {
  206. off_t allbutlast = tp->meta.piece_length * (tp->meta.npieces - 1);
  207. return tp->meta.total_length - allbutlast;
  208. }
  209. }
  210. uint32_t
  211. torrent_block_size(struct piece *pc, uint32_t index)
  212. {
  213. if (index < pc->nblocks - 1)
  214. return PIECE_BLOCKLEN;
  215. else {
  216. uint32_t allbutlast = PIECE_BLOCKLEN * (pc->nblocks - 1);
  217. return torrent_piece_size(pc->tp, pc->index) - allbutlast;
  218. }
  219. }
  220. int
  221. torrent_has_all(struct torrent *tp)
  222. {
  223. return tp->have_npieces == tp->meta.npieces;
  224. }