A clone of btpd with my configuration changes.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

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