A clone of btpd with my configuration changes.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

226 lines
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. }