A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

245 lignes
5.3 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. BTPDQ_INIT(&tp->peers);
  39. BTPDQ_INIT(&tp->getlst);
  40. tp->imem = mem;
  41. tp->isiz = memsiz;
  42. tp->piece_field = tp->imem;
  43. tp->block_field =
  44. (uint8_t *)tp->imem + (size_t)ceil(mi->npieces / 8.0);
  45. for (uint32_t i = 0; i < mi->npieces; i++)
  46. if (has_bit(tp->piece_field, i))
  47. tp->have_npieces++;
  48. tp->meta = *mi;
  49. free(mi);
  50. BTPDQ_INSERT_TAIL(&btpd.cm_list, tp, entry);
  51. tracker_req(tp, TR_STARTED);
  52. btpd.ntorrents++;
  53. return 0;
  54. }
  55. static int
  56. torrent_load2(const char *file, struct metainfo *mi)
  57. {
  58. int error, ifd;
  59. struct stat sb;
  60. char *mem;
  61. size_t memsiz;
  62. if ((error = vopen(&ifd, O_RDWR, "%s.i", file)) != 0) {
  63. btpd_log(BTPD_L_ERROR, "Error opening %s.i: %s.\n",
  64. file, strerror(error));
  65. return error;
  66. }
  67. if (fstat(ifd, &sb) == -1) {
  68. error = errno;
  69. btpd_log(BTPD_L_ERROR, "Error stating %s.i: %s.\n",
  70. file, strerror(error));
  71. close(ifd);
  72. return error;
  73. }
  74. memsiz =
  75. ceil(mi->npieces / 8.0) +
  76. ceil(mi->npieces * mi->piece_length / (double)(1 << 17));
  77. if (sb.st_size != memsiz) {
  78. btpd_log(BTPD_L_ERROR, "File has wrong size: %s.i.\n", file);
  79. close(ifd);
  80. return EINVAL;
  81. }
  82. mem = mmap(NULL, memsiz, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
  83. if (mem == MAP_FAILED)
  84. btpd_err("Error mmap'ing %s.i: %s.\n", file, strerror(errno));
  85. close(ifd);
  86. if ((error = torrent_load3(file, mi, mem, memsiz) != 0)) {
  87. munmap(mem, memsiz);
  88. return error;
  89. }
  90. return 0;
  91. }
  92. int
  93. torrent_load(const char *file)
  94. {
  95. struct metainfo *mi;
  96. int error;
  97. if ((error = load_metainfo(file, -1, 0, &mi)) != 0) {
  98. btpd_log(BTPD_L_ERROR, "Couldn't load metainfo file %s: %s.\n",
  99. file, strerror(error));
  100. return error;
  101. }
  102. if (torrent_get_by_hash(mi->info_hash) != NULL) {
  103. btpd_log(BTPD_L_BTPD, "%s has same hash as an already loaded torrent.\n", file);
  104. error = EEXIST;
  105. }
  106. if (error == 0)
  107. error = torrent_load2(file, mi);
  108. if (error != 0) {
  109. clear_metainfo(mi);
  110. free(mi);
  111. }
  112. return error;
  113. }
  114. void
  115. torrent_unload(struct torrent *tp)
  116. {
  117. struct peer *peer;
  118. struct piece *piece;
  119. btpd_log(BTPD_L_BTPD, "Unloading %s.\n", tp->relpath);
  120. tracker_req(tp, TR_STOPPED);
  121. peer = BTPDQ_FIRST(&tp->peers);
  122. while (peer != NULL) {
  123. struct peer *next = BTPDQ_NEXT(peer, cm_entry);
  124. peer->flags &= ~PF_ATTACHED;
  125. peer_kill(peer);
  126. peer = next;
  127. }
  128. piece = BTPDQ_FIRST(&tp->getlst);
  129. while (piece != NULL) {
  130. struct piece *next = BTPDQ_NEXT(piece, entry);
  131. free(piece);
  132. piece = next;
  133. }
  134. free(tp->piece_count);
  135. free((void *)tp->relpath);
  136. clear_metainfo(&tp->meta);
  137. munmap(tp->imem, tp->isiz);
  138. BTPDQ_REMOVE(&btpd.cm_list, tp, entry);
  139. free(tp);
  140. btpd.ntorrents--;
  141. }
  142. off_t
  143. torrent_bytes_left(struct torrent *tp)
  144. {
  145. if (tp->have_npieces == 0)
  146. return tp->meta.total_length;
  147. else if (has_bit(tp->piece_field, tp->meta.npieces - 1)) {
  148. return tp->meta.total_length -
  149. ((tp->have_npieces - 1) * tp->meta.piece_length +
  150. tp->meta.total_length % tp->meta.piece_length);
  151. } else
  152. return tp->meta.total_length -
  153. tp->have_npieces * tp->meta.piece_length;
  154. }
  155. char *
  156. torrent_get_bytes(struct torrent *tp, off_t start, size_t len)
  157. {
  158. char *buf = btpd_malloc(len);
  159. struct bt_stream_ro *bts;
  160. if ((bts = bts_open_ro(&tp->meta, start, ro_fd_cb, tp)) == NULL)
  161. btpd_err("Out of memory.\n");
  162. if (bts_read_ro(bts, buf, len) != 0)
  163. btpd_err("Io error.\n");
  164. bts_close_ro(bts);
  165. return buf;
  166. }
  167. void
  168. torrent_put_bytes(struct torrent *tp, const char *buf, off_t start, size_t len)
  169. {
  170. int err;
  171. struct bt_stream_wo *bts;
  172. if ((bts = bts_open_wo(&tp->meta, start, wo_fd_cb, tp)) == NULL)
  173. btpd_err("Out of memory.\n");
  174. if ((err = bts_write_wo(bts, buf, len)) != 0)
  175. btpd_err("Io error1: %s\n", strerror(err));
  176. if ((err = bts_close_wo(bts)) != 0)
  177. btpd_err("Io error2: %s\n", strerror(err));
  178. }
  179. int
  180. torrent_has_peer(struct torrent *tp, const uint8_t *id)
  181. {
  182. int has = 0;
  183. struct peer *p = BTPDQ_FIRST(&tp->peers);
  184. while (p != NULL) {
  185. if (bcmp(p->id, id, 20) == 0) {
  186. has = 1;
  187. break;
  188. }
  189. p = BTPDQ_NEXT(p, cm_entry);
  190. }
  191. return has;
  192. }
  193. struct torrent *
  194. torrent_get_by_hash(const uint8_t *hash)
  195. {
  196. struct torrent *tp = BTPDQ_FIRST(&btpd.cm_list);
  197. while (tp != NULL && bcmp(hash, tp->meta.info_hash, 20) != 0)
  198. tp = BTPDQ_NEXT(tp, entry);
  199. return tp;
  200. }