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.

284 lines
6.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 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.d/%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.d/%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. BTPDQ_INSERT_TAIL(&btpd.cm_list, tp, entry);
  52. tracker_req(tp, TR_STARTED);
  53. btpd.ntorrents++;
  54. return 0;
  55. }
  56. static int
  57. torrent_load2(const char *file, struct metainfo *mi)
  58. {
  59. int error, ifd;
  60. struct stat sb;
  61. char *mem;
  62. size_t memsiz;
  63. if ((error = vopen(&ifd, O_RDWR, "%s.i", 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. ceil(mi->npieces * 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 *file)
  95. {
  96. struct metainfo *mi;
  97. int error;
  98. if ((error = load_metainfo(file, -1, 0, &mi)) != 0) {
  99. btpd_log(BTPD_L_ERROR, "Couldn't load metainfo file %s: %s.\n",
  100. file, strerror(error));
  101. return error;
  102. }
  103. if (torrent_get_by_hash(mi->info_hash) != NULL) {
  104. btpd_log(BTPD_L_BTPD, "%s has same hash as an already loaded torrent.\n", file);
  105. error = EEXIST;
  106. }
  107. if (error == 0)
  108. error = torrent_load2(file, mi);
  109. if (error != 0) {
  110. clear_metainfo(mi);
  111. free(mi);
  112. }
  113. return error;
  114. }
  115. void
  116. torrent_unload(struct torrent *tp)
  117. {
  118. struct peer *peer;
  119. struct piece *piece;
  120. btpd_log(BTPD_L_BTPD, "Unloading %s.\n", tp->relpath);
  121. tracker_req(tp, TR_STOPPED);
  122. peer = BTPDQ_FIRST(&tp->peers);
  123. while (peer != NULL) {
  124. struct peer *next = BTPDQ_NEXT(peer, cm_entry);
  125. BTPDQ_REMOVE(&tp->peers, peer, cm_entry);
  126. BTPDQ_INSERT_TAIL(&btpd.unattached, peer, cm_entry);
  127. peer->flags &= ~PF_ATTACHED;
  128. peer = next;
  129. }
  130. peer = BTPDQ_FIRST(&btpd.unattached);
  131. while (peer != NULL) {
  132. struct peer *next = BTPDQ_NEXT(peer, cm_entry);
  133. if (peer->tp == tp)
  134. peer_kill(peer);
  135. peer = next;
  136. }
  137. piece = BTPDQ_FIRST(&tp->getlst);
  138. while (piece != NULL) {
  139. struct piece *next = BTPDQ_NEXT(piece, entry);
  140. free(piece);
  141. piece = next;
  142. }
  143. free(tp->piece_count);
  144. free(tp->busy_field);
  145. free((void *)tp->relpath);
  146. clear_metainfo(&tp->meta);
  147. munmap(tp->imem, tp->isiz);
  148. BTPDQ_REMOVE(&btpd.cm_list, tp, entry);
  149. free(tp);
  150. btpd.ntorrents--;
  151. }
  152. off_t
  153. torrent_bytes_left(struct torrent *tp)
  154. {
  155. if (tp->have_npieces == 0)
  156. return tp->meta.total_length;
  157. else if (has_bit(tp->piece_field, tp->meta.npieces - 1)) {
  158. return tp->meta.total_length -
  159. ((tp->have_npieces - 1) * tp->meta.piece_length +
  160. tp->meta.total_length % tp->meta.piece_length);
  161. } else
  162. return tp->meta.total_length -
  163. tp->have_npieces * tp->meta.piece_length;
  164. }
  165. char *
  166. torrent_get_bytes(struct torrent *tp, off_t start, size_t len)
  167. {
  168. char *buf = btpd_malloc(len);
  169. struct bt_stream_ro *bts;
  170. if ((bts = bts_open_ro(&tp->meta, start, ro_fd_cb, tp)) == NULL)
  171. btpd_err("Out of memory.\n");
  172. if (bts_read_ro(bts, buf, len) != 0)
  173. btpd_err("Io error.\n");
  174. bts_close_ro(bts);
  175. return buf;
  176. }
  177. void
  178. torrent_put_bytes(struct torrent *tp, const char *buf, off_t start, size_t len)
  179. {
  180. int err;
  181. struct bt_stream_wo *bts;
  182. if ((bts = bts_open_wo(&tp->meta, start, wo_fd_cb, tp)) == NULL)
  183. btpd_err("Out of memory.\n");
  184. if ((err = bts_write_wo(bts, buf, len)) != 0)
  185. btpd_err("Io error1: %s\n", strerror(err));
  186. if ((err = bts_close_wo(bts)) != 0)
  187. btpd_err("Io error2: %s\n", strerror(err));
  188. }
  189. int
  190. torrent_has_peer(struct torrent *tp, const uint8_t *id)
  191. {
  192. int has = 0;
  193. struct peer *p = BTPDQ_FIRST(&tp->peers);
  194. while (p != NULL) {
  195. if (bcmp(p->id, id, 20) == 0) {
  196. has = 1;
  197. break;
  198. }
  199. p = BTPDQ_NEXT(p, cm_entry);
  200. }
  201. return has;
  202. }
  203. struct torrent *
  204. torrent_get_by_hash(const uint8_t *hash)
  205. {
  206. struct torrent *tp = BTPDQ_FIRST(&btpd.cm_list);
  207. while (tp != NULL && bcmp(hash, tp->meta.info_hash, 20) != 0)
  208. tp = BTPDQ_NEXT(tp, entry);
  209. return tp;
  210. }
  211. off_t
  212. torrent_piece_size(struct torrent *tp, uint32_t index)
  213. {
  214. if (index < tp->meta.npieces - 1)
  215. return tp->meta.piece_length;
  216. else {
  217. off_t allbutlast = tp->meta.piece_length * (tp->meta.npieces - 1);
  218. return tp->meta.total_length - allbutlast;
  219. }
  220. }
  221. uint32_t
  222. torrent_block_size(struct piece *pc, uint32_t index)
  223. {
  224. if (index < pc->nblocks - 1)
  225. return PIECE_BLOCKLEN;
  226. else {
  227. uint32_t allbutlast = PIECE_BLOCKLEN * (pc->nblocks - 1);
  228. return torrent_piece_size(pc->tp, pc->index) - allbutlast;
  229. }
  230. }
  231. int
  232. torrent_has_all(struct torrent *tp)
  233. {
  234. return tp->have_npieces == tp->meta.npieces;
  235. }