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.

268 lignes
6.9 KiB

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <sys/un.h>
  4. #include <arpa/inet.h>
  5. #include <sys/stat.h>
  6. #include <inttypes.h>
  7. #include <limits.h>
  8. #include <stdarg.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include "btpd.h"
  13. #define buf_swrite(iob, s) buf_write(iob, s, sizeof(s) - 1)
  14. static struct event m_cli_incoming;
  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", net_npeers));
  29. errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents()));
  30. errdie(buf_swrite(&iob, "8:torrentsl"));
  31. BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) {
  32. if (tp->state != T_ACTIVE)
  33. continue;
  34. uint32_t seen_npieces = 0;
  35. for (uint32_t i = 0; i < tp->meta.npieces; i++)
  36. if (tp->net->piece_count[i] > 0)
  37. seen_npieces++;
  38. errdie(buf_print(&iob, "d4:downi%jue", (intmax_t)tp->net->downloaded));
  39. errdie(buf_swrite(&iob, "4:hash20:"));
  40. errdie(buf_write(&iob, tp->meta.info_hash, 20));
  41. errdie(buf_print(&iob, "4:havei%jde", (intmax_t)cm_get_size(tp)));
  42. errdie(buf_print(&iob, "6:npeersi%ue", tp->net->npeers));
  43. errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces));
  44. errdie(buf_print(&iob, "4:path%d:%s",
  45. (int)strlen(tp->relpath), tp->relpath));
  46. errdie(buf_print(&iob, "2:rdi%lue", tp->net->rate_dwn));
  47. errdie(buf_print(&iob, "2:rui%lue", tp->net->rate_up));
  48. errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces));
  49. errdie(buf_print(&iob, "5:totali%jde",
  50. (intmax_t)tp->meta.total_length));
  51. errdie(buf_print(&iob, "2:upi%juee", (intmax_t)tp->net->uploaded));
  52. }
  53. errdie(buf_swrite(&iob, "ee"));
  54. uint32_t len = iob.buf_off;
  55. fwrite(&len, sizeof(len), 1, fp);
  56. fwrite(iob.buf, 1, iob.buf_off, fp);
  57. free(iob.buf);
  58. }
  59. #if 0
  60. static void
  61. cmd_add(int argc, const char *args, FILE *fp)
  62. {
  63. struct io_buffer iob;
  64. errdie(buf_init(&iob, (1 << 10)));
  65. errdie(buf_write(&iob, "l", 1));
  66. while (args != NULL) {
  67. size_t plen;
  68. char path[PATH_MAX];
  69. const char *pathp;
  70. if (!benc_isstr(args)) {
  71. free(iob.buf);
  72. return;
  73. }
  74. benc_str(args, &pathp, &plen, &args);
  75. if (plen >= PATH_MAX) {
  76. errdie(buf_print(&iob, "d4:codei%dee", ENAMETOOLONG));
  77. continue;
  78. }
  79. bcopy(pathp, path, plen);
  80. path[plen] = '\0';
  81. btpd_log(BTPD_L_BTPD, "add request for %s.\n", path);
  82. errdie(buf_print(&iob, "d4:codei%dee", torrent_load(path)));
  83. }
  84. errdie(buf_write(&iob, "e", 1));
  85. uint32_t len = iob.buf_off;
  86. fwrite(&len, sizeof(len), 1, fp);
  87. fwrite(iob.buf, 1, iob.buf_off, fp);
  88. free(iob.buf);
  89. }
  90. static void
  91. cmd_del(int argc, const char *args, FILE *fp)
  92. {
  93. struct io_buffer iob;
  94. errdie(buf_init(&iob, (1 << 10)));
  95. errdie(buf_swrite(&iob, "l"));
  96. while (args != NULL) {
  97. size_t len;
  98. const char *hash;
  99. struct torrent *tp;
  100. if (!benc_isstr(args) ||
  101. benc_str(args, &hash, &len, &args) != 0 || len != 20) {
  102. free(iob.buf);
  103. return;
  104. }
  105. tp = btpd_get_torrent(hash);
  106. if (tp != NULL) {
  107. btpd_log(BTPD_L_BTPD, "del request for %s.\n", tp->relpath);
  108. torrent_unload(tp);
  109. errdie(buf_swrite(&iob, "d4:codei0ee"));
  110. } else {
  111. btpd_log(BTPD_L_BTPD, "del request didn't match.\n");
  112. errdie(buf_print(&iob, "d4:codei%dee", ENOENT));
  113. }
  114. }
  115. errdie(buf_swrite(&iob, "e"));
  116. uint32_t len = iob.buf_off;
  117. fwrite(&len, sizeof(len), 1, fp);
  118. fwrite(iob.buf, 1, iob.buf_off, fp);
  119. free(iob.buf);
  120. }
  121. static void
  122. cmd_die(int argc, const char *args, FILE *fp)
  123. {
  124. char res[] = "d4:codei0ee";
  125. uint32_t len = sizeof(res) - 1;
  126. fwrite(&len, sizeof(len), 1, fp);
  127. fwrite(res, 1, len, fp);
  128. fflush(fp);
  129. btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n");
  130. btpd_shutdown();
  131. }
  132. #endif
  133. static struct {
  134. const char *name;
  135. int nlen;
  136. void (*fun)(int, const char *, FILE *);
  137. } cmd_table[] = {
  138. #if 0
  139. { "add", 3, cmd_add },
  140. { "del", 3, cmd_del },
  141. { "die", 3, cmd_die },
  142. #endif
  143. { "stat", 4, cmd_stat }
  144. };
  145. static int ncmds = sizeof(cmd_table) / sizeof(cmd_table[0]);
  146. static void
  147. cmd_dispatch(const char *buf, FILE *fp)
  148. {
  149. size_t cmdlen;
  150. const char *cmd;
  151. const char *args;
  152. int found = 0;
  153. benc_str(benc_first(buf), &cmd, &cmdlen, &args);
  154. for (int i = 0; !found && i < ncmds; i++) {
  155. if (cmdlen == cmd_table[i].nlen &&
  156. strncmp(cmd_table[i].name, cmd, cmdlen) == 0) {
  157. cmd_table[i].fun(benc_nelems(buf) - 1, args, fp);
  158. found = 1;
  159. }
  160. }
  161. }
  162. static void
  163. do_ipc(FILE *fp)
  164. {
  165. uint32_t cmdlen, nread;
  166. char *buf;
  167. if (fread(&cmdlen, sizeof(cmdlen), 1, fp) != 1)
  168. return;
  169. buf = btpd_malloc(cmdlen);
  170. if ((nread = fread(buf, 1, cmdlen, fp)) == cmdlen) {
  171. if (benc_validate(buf, cmdlen) == 0 && benc_islst(buf) &&
  172. benc_first(buf) != NULL && benc_isstr(benc_first(buf)))
  173. cmd_dispatch(buf, fp);
  174. }
  175. free(buf);
  176. }
  177. void
  178. client_connection_cb(int sd, short type, void *arg)
  179. {
  180. int nsd;
  181. FILE *fp;
  182. if ((nsd = accept(sd, NULL, NULL)) < 0) {
  183. if (errno == EWOULDBLOCK || errno == ECONNABORTED)
  184. return;
  185. else
  186. btpd_err("client accept: %s\n", strerror(errno));
  187. }
  188. if ((errno = set_blocking(nsd)) != 0)
  189. btpd_err("set_blocking: %s.\n", strerror(errno));
  190. if ((fp = fdopen(nsd, "r+")) == NULL) {
  191. close(nsd);
  192. return;
  193. }
  194. do_ipc(fp);
  195. fclose(fp);
  196. }
  197. void
  198. ipc_init(void)
  199. {
  200. int sd;
  201. struct sockaddr_un addr;
  202. size_t psiz = sizeof(addr.sun_path);
  203. addr.sun_family = PF_UNIX;
  204. if (snprintf(addr.sun_path, psiz, "%s/sock", btpd_dir) >= psiz)
  205. btpd_err("'%s/sock' is too long.\n", btpd_dir);
  206. if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  207. btpd_err("sock: %s\n", strerror(errno));
  208. if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
  209. if (errno == EADDRINUSE) {
  210. unlink(addr.sun_path);
  211. if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
  212. btpd_err("bind: %s\n", strerror(errno));
  213. } else
  214. btpd_err("bind: %s\n", strerror(errno));
  215. }
  216. if (chmod(addr.sun_path, 0600) == -1)
  217. btpd_err("chmod: %s (%s).\n", addr.sun_path, strerror(errno));
  218. listen(sd, 4);
  219. set_nonblocking(sd);
  220. event_set(&m_cli_incoming, sd, EV_READ | EV_PERSIST,
  221. client_connection_cb, NULL);
  222. event_add(&m_cli_incoming, NULL);
  223. }