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

268 行
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. }