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.

226 lignes
5.3 KiB

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <inttypes.h>
  5. #include <limits.h>
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include "btpd.h"
  11. #ifndef PRIu64
  12. #define PRIu64 "llu"
  13. #endif
  14. #define buf_swrite(iob, s) buf_write(iob, s, sizeof(s) - 1)
  15. static void
  16. errdie(int error)
  17. {
  18. if (error != 0)
  19. btpd_err("io_buf: %s.\n", strerror(error));
  20. }
  21. static void
  22. cmd_stat(int argc, const char *args, FILE *fp)
  23. {
  24. struct torrent *tp;
  25. struct io_buffer iob;
  26. errdie(buf_init(&iob, (1 << 14)));
  27. errdie(buf_swrite(&iob, "d"));
  28. errdie(buf_print(&iob, "6:npeersi%ue", btpd.npeers));
  29. errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd.ntorrents));
  30. errdie(buf_print(&iob, "7:secondsi%lue", btpd.seconds));
  31. errdie(buf_swrite(&iob, "8:torrentsl"));
  32. BTPDQ_FOREACH(tp, &btpd.cm_list, entry) {
  33. uint32_t seen_npieces = 0;
  34. for (uint32_t i = 0; i < tp->meta.npieces; i++)
  35. if (tp->piece_count[i] > 0)
  36. seen_npieces++;
  37. errdie(buf_print(&iob, "d4:downi%" PRIu64 "e", tp->downloaded));
  38. errdie(buf_swrite(&iob, "4:hash20:"));
  39. errdie(buf_write(&iob, tp->meta.info_hash, 20));
  40. errdie(buf_print(&iob, "12:have npiecesi%ue", tp->have_npieces));
  41. errdie(buf_print(&iob, "6:npeersi%ue", tp->npeers));
  42. errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces));
  43. errdie(buf_print(&iob, "4:path%d:%s",
  44. (int)strlen(tp->relpath), tp->relpath));
  45. errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces));
  46. errdie(buf_print(&iob, "2:upi%" PRIu64 "ee", tp->uploaded));
  47. }
  48. errdie(buf_swrite(&iob, "ee"));
  49. uint32_t len = iob.buf_off;
  50. fwrite(&len, sizeof(len), 1, fp);
  51. fwrite(iob.buf, 1, iob.buf_off, fp);
  52. free(iob.buf);
  53. }
  54. static void
  55. cmd_add(int argc, const char *args, FILE *fp)
  56. {
  57. struct io_buffer iob;
  58. errdie(buf_init(&iob, (1 << 10)));
  59. errdie(buf_write(&iob, "l", 1));
  60. while (args != NULL) {
  61. size_t plen;
  62. char path[PATH_MAX];
  63. const char *pathp;
  64. if (!benc_isstr(args)) {
  65. free(iob.buf);
  66. return;
  67. }
  68. benc_str(args, &pathp, &plen, &args);
  69. if (plen >= PATH_MAX) {
  70. errdie(buf_print(&iob, "d4:codei%dee", ENAMETOOLONG));
  71. continue;
  72. }
  73. bcopy(pathp, path, plen);
  74. path[plen] = '\0';
  75. btpd_log(BTPD_L_BTPD, "add request for %s.\n", path);
  76. errdie(buf_print(&iob, "d4:codei%dee", torrent_load(path)));
  77. }
  78. errdie(buf_write(&iob, "e", 1));
  79. uint32_t len = iob.buf_off;
  80. fwrite(&len, sizeof(len), 1, fp);
  81. fwrite(iob.buf, 1, iob.buf_off, fp);
  82. free(iob.buf);
  83. }
  84. static void
  85. cmd_del(int argc, const char *args, FILE *fp)
  86. {
  87. struct io_buffer iob;
  88. errdie(buf_init(&iob, (1 << 10)));
  89. errdie(buf_swrite(&iob, "l"));
  90. while (args != NULL) {
  91. size_t len;
  92. const char *hash;
  93. struct torrent *tp;
  94. if (!benc_isstr(args) ||
  95. benc_str(args, &hash, &len, &args) != 0 || len != 20) {
  96. free(iob.buf);
  97. return;
  98. }
  99. tp = torrent_get_by_hash(hash);
  100. if (tp != NULL) {
  101. btpd_log(BTPD_L_BTPD, "del request for %s.\n", tp->relpath);
  102. torrent_unload(tp);
  103. errdie(buf_swrite(&iob, "d4:codei0ee"));
  104. } else {
  105. btpd_log(BTPD_L_BTPD, "del request didn't match.\n");
  106. errdie(buf_print(&iob, "d4:codei%dee", ENOENT));
  107. }
  108. }
  109. errdie(buf_swrite(&iob, "e"));
  110. uint32_t len = iob.buf_off;
  111. fwrite(&len, sizeof(len), 1, fp);
  112. fwrite(iob.buf, 1, iob.buf_off, fp);
  113. free(iob.buf);
  114. }
  115. static void
  116. cmd_die(int argc, const char *args, FILE *fp)
  117. {
  118. char res[] = "d4:codei0ee";
  119. uint32_t len = sizeof(res) - 1;
  120. fwrite(&len, sizeof(len), 1, fp);
  121. fwrite(res, 1, len, fp);
  122. fflush(fp);
  123. btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n");
  124. btpd_shutdown();
  125. }
  126. static struct {
  127. const char *name;
  128. int nlen;
  129. void (*fun)(int, const char *, FILE *);
  130. } cmd_table[] = {
  131. { "add", 3, cmd_add },
  132. { "del", 3, cmd_del },
  133. { "die", 3, cmd_die },
  134. { "stat", 4, cmd_stat }
  135. };
  136. static int ncmds = sizeof(cmd_table) / sizeof(cmd_table[0]);
  137. static void
  138. cmd_dispatch(const char *buf, FILE *fp)
  139. {
  140. size_t cmdlen;
  141. const char *cmd;
  142. const char *args;
  143. int found = 0;
  144. benc_str(benc_first(buf), &cmd, &cmdlen, &args);
  145. for (int i = 0; !found && i < ncmds; i++) {
  146. if (cmdlen == cmd_table[i].nlen &&
  147. strncmp(cmd_table[i].name, cmd, cmdlen) == 0) {
  148. cmd_table[i].fun(benc_nelems(buf) - 1, args, fp);
  149. found = 1;
  150. }
  151. }
  152. }
  153. static void
  154. do_ipc(FILE *fp)
  155. {
  156. uint32_t cmdlen, nread;
  157. char *buf;
  158. if (fread(&cmdlen, sizeof(cmdlen), 1, fp) != 1)
  159. return;
  160. buf = btpd_malloc(cmdlen);
  161. if ((nread = fread(buf, 1, cmdlen, fp)) == cmdlen) {
  162. if (benc_validate(buf, cmdlen) == 0 && benc_islst(buf) &&
  163. benc_first(buf) != NULL && benc_isstr(benc_first(buf)))
  164. cmd_dispatch(buf, fp);
  165. }
  166. free(buf);
  167. }
  168. void
  169. client_connection_cb(int sd, short type, void *arg)
  170. {
  171. int nsd;
  172. FILE *fp;
  173. if ((nsd = accept(sd, NULL, NULL)) < 0) {
  174. if (errno == EWOULDBLOCK || errno == ECONNABORTED)
  175. return;
  176. else
  177. btpd_err("client accept: %s\n", strerror(errno));
  178. }
  179. if ((errno = set_blocking(nsd)) != 0)
  180. btpd_err("set_blocking: %s.\n", strerror(errno));
  181. if ((fp = fdopen(nsd, "r+")) == NULL) {
  182. close(nsd);
  183. return;
  184. }
  185. do_ipc(fp);
  186. fclose(fp);
  187. }