A clone of btpd with my configuration changes.

491 行
14 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. #include "active.h"
  14. #include "tracker_req.h"
  15. struct cli {
  16. int sd;
  17. struct event read;
  18. };
  19. static struct event m_cli_incoming;
  20. static int
  21. write_buffer(struct cli *cli, struct io_buffer *iob)
  22. {
  23. int err = 0;
  24. if (!iob->error) {
  25. uint32_t len = iob->buf_off;
  26. write_fully(cli->sd, &len, sizeof(len));
  27. err = write_fully(cli->sd, iob->buf, iob->buf_off);
  28. } else
  29. btpd_err("Out of memory.\n");
  30. if (iob->buf != NULL)
  31. free(iob->buf);
  32. return err;
  33. }
  34. static int
  35. write_code_buffer(struct cli *cli, enum ipc_err code)
  36. {
  37. struct io_buffer iob;
  38. buf_init(&iob, 16);
  39. buf_print(&iob, "d4:codei%uee", code);
  40. return write_buffer(cli, &iob);
  41. }
  42. static int
  43. write_add_buffer(struct cli *cli, unsigned num)
  44. {
  45. struct io_buffer iob;
  46. buf_init(&iob, 32);
  47. buf_print(&iob, "d4:codei%ue3:numi%uee", IPC_OK, num);
  48. return write_buffer(cli, &iob);
  49. }
  50. static void
  51. write_ans(struct io_buffer *iob, struct tlib *tl, enum ipc_tval val)
  52. {
  53. enum ipc_tstate ts = IPC_TSTATE_INACTIVE;
  54. switch (val) {
  55. case IPC_TVAL_CGOT:
  56. if (tl->tp == NULL)
  57. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  58. else
  59. buf_print(iob, "i%dei%llde", IPC_TYPE_NUM,
  60. (long long)cm_content(tl->tp));
  61. return;
  62. case IPC_TVAL_CSIZE:
  63. if (tl->tp == NULL)
  64. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  65. else
  66. buf_print(iob, "i%dei%llde", IPC_TYPE_NUM,
  67. (long long)tl->tp->total_length);
  68. return;
  69. case IPC_TVAL_PCCOUNT:
  70. if (tl->tp == NULL)
  71. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  72. else
  73. buf_print(iob, "i%dei%lue", IPC_TYPE_NUM,
  74. (unsigned long)tl->tp->npieces);
  75. return;
  76. case IPC_TVAL_PCGOT:
  77. if (tl->tp == NULL)
  78. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  79. else
  80. buf_print(iob, "i%dei%lue", IPC_TYPE_NUM,
  81. (unsigned long)cm_pieces(tl->tp));
  82. return;
  83. case IPC_TVAL_PCSEEN:
  84. if (tl->tp == NULL)
  85. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  86. else {
  87. unsigned long pcseen = 0;
  88. for (unsigned long i = 0; i < tl->tp->npieces; i++)
  89. if (tl->tp->net->piece_count[i] > 0)
  90. pcseen++;
  91. buf_print(iob, "i%dei%lue", IPC_TYPE_NUM, pcseen);
  92. }
  93. return;
  94. case IPC_TVAL_RATEDWN:
  95. if (tl->tp == NULL)
  96. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  97. else
  98. buf_print(iob, "i%dei%lue", IPC_TYPE_NUM, tl->tp->net->rate_dwn);
  99. return;
  100. case IPC_TVAL_RATEUP:
  101. if (tl->tp == NULL)
  102. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  103. else
  104. buf_print(iob, "i%dei%lue", IPC_TYPE_NUM, tl->tp->net->rate_up);
  105. return;
  106. case IPC_TVAL_SESSDWN:
  107. if (tl->tp == NULL)
  108. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  109. else
  110. buf_print(iob, "i%dei%llde", IPC_TYPE_NUM,
  111. tl->tp->net->downloaded);
  112. return;
  113. case IPC_TVAL_SESSUP:
  114. if (tl->tp == NULL)
  115. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ETINACTIVE);
  116. else
  117. buf_print(iob, "i%dei%llde", IPC_TYPE_NUM, tl->tp->net->uploaded);
  118. return;
  119. case IPC_TVAL_DIR:
  120. if (tl->dir != NULL)
  121. buf_print(iob, "i%de%d:%s", IPC_TYPE_STR, (int)strlen(tl->dir),
  122. tl->dir);
  123. else
  124. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_EBADTENT);
  125. return;
  126. case IPC_TVAL_NAME:
  127. if (tl->name != NULL)
  128. buf_print(iob, "i%de%d:%s", IPC_TYPE_STR, (int)strlen(tl->name),
  129. tl->name);
  130. else
  131. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_EBADTENT);
  132. return;
  133. case IPC_TVAL_IHASH:
  134. buf_print(iob, "i%de20:", IPC_TYPE_BIN);
  135. buf_write(iob, tl->hash, 20);
  136. return;
  137. case IPC_TVAL_NUM:
  138. buf_print(iob, "i%dei%ue", IPC_TYPE_NUM, tl->num);
  139. return;
  140. case IPC_TVAL_PCOUNT:
  141. buf_print(iob, "i%dei%ue", IPC_TYPE_NUM,
  142. tl->tp == NULL ? 0 : tl->tp->net->npeers);
  143. return;
  144. case IPC_TVAL_STATE:
  145. buf_print(iob, "i%de", IPC_TYPE_NUM);
  146. if (tl->tp != NULL) {
  147. switch (tl->tp->state) {
  148. case T_STARTING:
  149. ts = IPC_TSTATE_START;
  150. break;
  151. case T_STOPPING:
  152. ts= IPC_TSTATE_STOP;
  153. break;
  154. case T_ACTIVE:
  155. if (cm_full(tl->tp))
  156. ts = IPC_TSTATE_SEED;
  157. else
  158. ts = IPC_TSTATE_LEECH;
  159. break;
  160. }
  161. }
  162. buf_print(iob, "i%de", ts);
  163. return;
  164. case IPC_TVAL_TRERR:
  165. buf_print(iob, "i%dei%ue", IPC_TYPE_NUM,
  166. tl->tp == NULL ? 0 : tr_errors(tl->tp));
  167. return;
  168. case IPC_TVALCOUNT:
  169. break;
  170. }
  171. buf_print(iob, "i%dei%de", IPC_TYPE_ERR, IPC_ENOKEY);
  172. }
  173. static int
  174. cmd_tget(struct cli *cli, int argc, const char *args)
  175. {
  176. if (argc != 1 || !benc_isdct(args))
  177. return IPC_COMMERR;
  178. size_t nkeys;
  179. const char *keys, *p;
  180. enum ipc_tval *opts;
  181. struct io_buffer iob;
  182. if ((keys = benc_dget_lst(args, "keys")) == NULL)
  183. return IPC_COMMERR;
  184. nkeys = benc_nelems(keys);
  185. opts = btpd_calloc(nkeys, sizeof(*opts));
  186. p = benc_first(keys);
  187. for (int i = 0; i < nkeys; i++)
  188. opts[i] = benc_int(p, &p);
  189. buf_init(&iob, (1 << 15));
  190. buf_swrite(&iob, "d4:codei0e6:resultl");
  191. p = benc_dget_any(args, "from");
  192. if (benc_isint(p)) {
  193. enum ipc_twc from = benc_int(p, NULL);
  194. struct tlib *tlv[tlib_count()];
  195. tlib_put_all(tlv);
  196. for (int i = 0; i < sizeof(tlv) / sizeof(tlv[0]); i++) {
  197. if ((from == IPC_TWC_ALL ||
  198. (tlv[i]->tp == NULL && from == IPC_TWC_INACTIVE) ||
  199. (tlv[i]->tp != NULL && from == IPC_TWC_ACTIVE))) {
  200. buf_swrite(&iob, "l");
  201. for (int k = 0; k < nkeys; k++)
  202. write_ans(&iob, tlv[i], opts[k]);
  203. buf_swrite(&iob, "e");
  204. }
  205. }
  206. } else if (benc_islst(p)) {
  207. for (p = benc_first(p); p != NULL; p = benc_next(p)) {
  208. struct tlib *tl = NULL;
  209. if (benc_isint(p))
  210. tl = tlib_by_num(benc_int(p, NULL));
  211. else if (benc_isstr(p) && benc_strlen(p) == 20)
  212. tl = tlib_by_hash(benc_mem(p, NULL, NULL));
  213. else {
  214. free(iob.buf);
  215. free(opts);
  216. return IPC_COMMERR;
  217. }
  218. if (tl != NULL) {
  219. buf_swrite(&iob, "l");
  220. for (int i = 0; i < nkeys; i++)
  221. write_ans(&iob, tl, opts[i]);
  222. buf_swrite(&iob, "e");
  223. } else
  224. buf_print(&iob, "i%de", IPC_ENOTENT);
  225. }
  226. }
  227. buf_swrite(&iob, "ee");
  228. free(opts);
  229. return write_buffer(cli, &iob);
  230. }
  231. static int
  232. cmd_add(struct cli *cli, int argc, const char *args)
  233. {
  234. if (argc != 1 || !benc_isdct(args))
  235. return IPC_COMMERR;
  236. struct tlib *tl;
  237. size_t mi_size = 0, csize = 0;
  238. const char *mi, *cp;
  239. char content[PATH_MAX];
  240. uint8_t hash[20];
  241. if ((mi = benc_dget_mem(args, "torrent", &mi_size)) == NULL)
  242. return IPC_COMMERR;
  243. if (!mi_test(mi, mi_size))
  244. return write_code_buffer(cli, IPC_EBADT);
  245. if ((cp = benc_dget_mem(args, "content", &csize)) == NULL ||
  246. csize >= PATH_MAX || csize == 0)
  247. return write_code_buffer(cli, IPC_EBADCDIR);
  248. if (cp[0] != '/')
  249. return write_code_buffer(cli, IPC_EBADCDIR);
  250. bcopy(cp, content, csize);
  251. content[csize] = '\0';
  252. tl = tlib_by_hash(mi_info_hash(mi, hash));
  253. if (tl != NULL)
  254. return write_code_buffer(cli, IPC_ETENTEXIST);
  255. tl = tlib_add(hash, mi, mi_size, content,
  256. benc_dget_str(args, "name", NULL));
  257. return write_add_buffer(cli, tl->num);
  258. }
  259. static int
  260. cmd_del(struct cli *cli, int argc, const char *args)
  261. {
  262. if (argc != 1)
  263. return IPC_COMMERR;
  264. struct tlib *tl;
  265. enum ipc_err code = IPC_OK;
  266. if (benc_isstr(args) && benc_strlen(args) == 20)
  267. tl = tlib_by_hash(benc_mem(args, NULL, NULL));
  268. else if (benc_isint(args))
  269. tl = tlib_by_num(benc_int(args, NULL));
  270. else
  271. return IPC_COMMERR;
  272. if (tl == NULL)
  273. code = IPC_ENOTENT;
  274. else if (tl->tp != NULL)
  275. code = IPC_ETACTIVE;
  276. else
  277. tlib_del(tl);
  278. return write_code_buffer(cli, code);
  279. }
  280. static int
  281. cmd_start(struct cli *cli, int argc, const char *args)
  282. {
  283. if (argc != 1)
  284. return IPC_COMMERR;
  285. if (btpd_is_stopping())
  286. return write_code_buffer(cli, IPC_ESHUTDOWN);
  287. struct tlib *tl;
  288. enum ipc_err code = IPC_OK;
  289. if (benc_isstr(args) && benc_strlen(args) == 20)
  290. tl = tlib_by_hash(benc_mem(args, NULL, NULL));
  291. else if (benc_isint(args))
  292. tl = tlib_by_num(benc_int(args, NULL));
  293. else
  294. return IPC_COMMERR;
  295. if (tl == NULL)
  296. code = IPC_ENOTENT;
  297. else if (tl->tp != NULL)
  298. code = IPC_ETACTIVE;
  299. else
  300. if ((code = torrent_start(tl)) == IPC_OK)
  301. active_add(tl->hash);
  302. return write_code_buffer(cli, code);
  303. }
  304. static int
  305. cmd_stop(struct cli *cli, int argc, const char *args)
  306. {
  307. if (argc != 1)
  308. return IPC_COMMERR;
  309. struct tlib *tl;
  310. if (benc_isstr(args) && benc_strlen(args) == 20)
  311. tl = tlib_by_hash(benc_mem(args, NULL, NULL));
  312. else if (benc_isint(args))
  313. tl = tlib_by_num(benc_int(args, NULL));
  314. else
  315. return IPC_COMMERR;
  316. if (tl == NULL)
  317. return write_code_buffer(cli, IPC_ENOTENT);
  318. else if (tl->tp == NULL)
  319. return write_code_buffer(cli, IPC_ETINACTIVE);
  320. else {
  321. // Stopping a torrent may trigger exit so we need to reply before.
  322. int ret = write_code_buffer(cli, IPC_OK);
  323. active_del(tl->hash);
  324. torrent_stop(tl->tp);
  325. return ret;
  326. }
  327. }
  328. static int
  329. cmd_die(struct cli *cli, int argc, const char *args)
  330. {
  331. int err = write_code_buffer(cli, IPC_OK);
  332. if (!btpd_is_stopping()) {
  333. int grace_seconds = -1;
  334. if (argc == 1 && benc_isint(args))
  335. grace_seconds = benc_int(args, NULL);
  336. btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n");
  337. btpd_shutdown(grace_seconds);
  338. }
  339. return err;
  340. }
  341. static struct {
  342. const char *name;
  343. int nlen;
  344. int (*fun)(struct cli *cli, int, const char *);
  345. } cmd_table[] = {
  346. { "add", 3, cmd_add },
  347. { "del", 3, cmd_del },
  348. { "die", 3, cmd_die },
  349. { "start", 5, cmd_start },
  350. { "stop", 4, cmd_stop },
  351. { "tget", 4, cmd_tget }
  352. };
  353. static int ncmds = sizeof(cmd_table) / sizeof(cmd_table[0]);
  354. static int
  355. cmd_dispatch(struct cli *cli, const char *buf)
  356. {
  357. size_t cmdlen;
  358. const char *cmd;
  359. const char *args;
  360. cmd = benc_mem(benc_first(buf), &cmdlen, &args);
  361. for (int i = 0; i < ncmds; i++) {
  362. if ((cmdlen == cmd_table[i].nlen &&
  363. strncmp(cmd_table[i].name, cmd, cmdlen) == 0)) {
  364. return cmd_table[i].fun(cli, benc_nelems(buf) - 1, args);
  365. }
  366. }
  367. return ENOENT;
  368. }
  369. static void
  370. cli_read_cb(int sd, short type, void *arg)
  371. {
  372. struct cli *cli = arg;
  373. uint32_t cmdlen;
  374. uint8_t *msg = NULL;
  375. if (read_fully(sd, &cmdlen, sizeof(cmdlen)) != 0)
  376. goto error;
  377. msg = btpd_malloc(cmdlen);
  378. if (read_fully(sd, msg, cmdlen) != 0)
  379. goto error;
  380. if (!(benc_validate(msg, cmdlen) == 0 && benc_islst(msg) &&
  381. benc_first(msg) != NULL && benc_isstr(benc_first(msg))))
  382. goto error;
  383. if (cmd_dispatch(cli, msg) != 0)
  384. goto error;
  385. free(msg);
  386. btpd_ev_add(&cli->read, NULL);
  387. return;
  388. error:
  389. close(cli->sd);
  390. free(cli);
  391. if (msg != NULL)
  392. free(msg);
  393. }
  394. void
  395. client_connection_cb(int sd, short type, void *arg)
  396. {
  397. int nsd;
  398. if ((nsd = accept(sd, NULL, NULL)) < 0) {
  399. if (errno == EWOULDBLOCK || errno == ECONNABORTED)
  400. return;
  401. else
  402. btpd_err("client accept: %s\n", strerror(errno));
  403. }
  404. if ((errno = set_blocking(nsd)) != 0)
  405. btpd_err("set_blocking: %s.\n", strerror(errno));
  406. struct cli *cli = btpd_calloc(1, sizeof(*cli));
  407. cli->sd = nsd;
  408. event_set(&cli->read, cli->sd, EV_READ, cli_read_cb, cli);
  409. btpd_ev_add(&cli->read, NULL);
  410. }
  411. void
  412. ipc_init(void)
  413. {
  414. int sd;
  415. struct sockaddr_un addr;
  416. size_t psiz = sizeof(addr.sun_path);
  417. addr.sun_family = PF_UNIX;
  418. if (snprintf(addr.sun_path, psiz, "%s/sock", btpd_dir) >= psiz)
  419. btpd_err("'%s/sock' is too long.\n", btpd_dir);
  420. if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  421. btpd_err("sock: %s\n", strerror(errno));
  422. if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
  423. if (errno == EADDRINUSE) {
  424. unlink(addr.sun_path);
  425. if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
  426. btpd_err("bind: %s\n", strerror(errno));
  427. } else
  428. btpd_err("bind: %s\n", strerror(errno));
  429. }
  430. if (chmod(addr.sun_path, ipcprot) == -1)
  431. btpd_err("chmod: %s (%s).\n", addr.sun_path, strerror(errno));
  432. listen(sd, 4);
  433. set_nonblocking(sd);
  434. event_set(&m_cli_incoming, sd, EV_READ | EV_PERSIST,
  435. client_connection_cb, NULL);
  436. btpd_ev_add(&m_cli_incoming, NULL);
  437. }