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.0 KiB

  1. #include <ctype.h>
  2. #include <err.h>
  3. #include <errno.h>
  4. #include <inttypes.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include "benc.h"
  10. #include "btpd_if.h"
  11. #include "iobuf.h"
  12. #include "subr.h"
  13. struct ipc {
  14. int sd;
  15. };
  16. int
  17. ipc_open(const char *dir, struct ipc **out)
  18. {
  19. int sd = -1, err = 0;
  20. size_t plen;
  21. struct ipc *res;
  22. struct sockaddr_un addr;
  23. plen = sizeof(addr.sun_path);
  24. if (snprintf(addr.sun_path, plen, "%s/sock", dir) >= plen)
  25. return ENAMETOOLONG;
  26. addr.sun_family = AF_UNIX;
  27. if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
  28. return errno;
  29. if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  30. err = errno;
  31. close(sd);
  32. return err;
  33. }
  34. if ((res = malloc(sizeof(*res))) == NULL) {
  35. close(sd);
  36. return ENOMEM;
  37. }
  38. res->sd = sd;
  39. *out = res;
  40. return 0;
  41. }
  42. int
  43. ipc_close(struct ipc *ipc)
  44. {
  45. int err;
  46. err = close(ipc->sd);
  47. free(ipc);
  48. return err;
  49. }
  50. static int
  51. ipc_response(struct ipc *ipc, char **out, uint32_t *len)
  52. {
  53. uint32_t size;
  54. char *buf;
  55. if ((errno = read_fully(ipc->sd, &size, sizeof(size))) != 0)
  56. return errno;
  57. if (size == 0)
  58. return ECONNRESET;
  59. if ((buf = malloc(size)) == NULL)
  60. return ENOMEM;
  61. if ((errno = read_fully(ipc->sd, buf, size)) != 0) {
  62. free(buf);
  63. return errno;
  64. }
  65. *out = buf;
  66. *len = size;
  67. return 0;
  68. }
  69. static int
  70. ipc_req_res(struct ipc *ipc, const char *req, uint32_t qlen, char **res,
  71. uint32_t *rlen)
  72. {
  73. if ((errno = write_fully(ipc->sd, &qlen, sizeof(qlen))) != 0)
  74. goto error;
  75. if ((errno = write_fully(ipc->sd, req, qlen)) != 0)
  76. goto error;
  77. if ((errno = ipc_response(ipc, res, rlen)) != 0)
  78. goto error;
  79. if ((errno = benc_validate(*res, *rlen)) != 0)
  80. goto error;
  81. if (!benc_isdct(*res))
  82. errno = EINVAL;
  83. error:
  84. return errno;
  85. }
  86. static enum ipc_code
  87. ipc_buf_req(struct ipc *ipc, struct io_buffer *iob)
  88. {
  89. int err;
  90. char *res;
  91. size_t reslen;
  92. err = ipc_req_res(ipc, iob->buf, iob->buf_off, &res, &reslen);
  93. free(iob->buf);
  94. if (err != 0)
  95. return IPC_COMMERR;
  96. int code;
  97. code = benc_dget_int(res, "code");
  98. free(res);
  99. return code;
  100. }
  101. enum ipc_code
  102. btpd_die(struct ipc *ipc, int seconds)
  103. {
  104. struct io_buffer iob;
  105. buf_init(&iob, 16);
  106. if (seconds >= 0)
  107. buf_print(&iob, "l3:diei%dee", seconds);
  108. else
  109. buf_print(&iob, "l3:diee");
  110. return ipc_buf_req(ipc, &iob);
  111. }
  112. enum ipc_code
  113. parse_btstat(const uint8_t *res, struct btstat **out)
  114. {
  115. int code;
  116. unsigned ntorrents;
  117. const char *tlst;
  118. code = benc_dget_int(res, "code");
  119. if (code != IPC_OK)
  120. return code;
  121. ntorrents = benc_dget_int(res, "ntorrents");
  122. tlst = benc_dget_lst(res, "torrents");
  123. struct btstat *st =
  124. malloc(sizeof(struct btstat) + sizeof(struct tpstat) * ntorrents);
  125. st->ntorrents = ntorrents;
  126. int i = 0;
  127. for (const char *tp = benc_first(tlst); tp != NULL; tp = benc_next(tp)) {
  128. struct tpstat *ts = &st->torrents[i];
  129. ts->num = benc_dget_int(tp, "num");
  130. ts->name = benc_dget_str(tp, "path", NULL);
  131. ts->state = *benc_dget_str(tp, "state", NULL);
  132. if (ts->state == 'A') {
  133. ts->errors = benc_dget_int(tp, "errors");
  134. ts->npieces = benc_dget_int(tp, "npieces");
  135. ts->nseen = benc_dget_int(tp, "seen npieces");
  136. ts->npeers = benc_dget_int(tp, "npeers");
  137. ts->downloaded = benc_dget_int(tp, "downloaded");
  138. ts->uploaded = benc_dget_int(tp, "uploaded");
  139. ts->rate_down = benc_dget_int(tp, "rd");
  140. ts->rate_up = benc_dget_int(tp, "ru");
  141. ts->have = benc_dget_int(tp, "have");
  142. ts->total = benc_dget_int(tp, "total");
  143. }
  144. i++;
  145. }
  146. *out = st;
  147. return IPC_OK;
  148. }
  149. void
  150. free_btstat(struct btstat *st)
  151. {
  152. for (unsigned i = 0; i < st->ntorrents; i++)
  153. if (st->torrents[i].name != NULL)
  154. free(st->torrents[i].name);
  155. free(st);
  156. }
  157. enum ipc_code
  158. btpd_stat(struct ipc *ipc, struct btstat **out)
  159. {
  160. int err;
  161. const char cmd[] = "l4:state";
  162. uint32_t cmdlen = sizeof(cmd) - 1;
  163. char *res;
  164. uint32_t reslen;
  165. if ((err = ipc_req_res(ipc, cmd, cmdlen, &res, &reslen)) != 0)
  166. return IPC_COMMERR;
  167. err = parse_btstat(res, out);
  168. free(res);
  169. return err;
  170. }
  171. static enum ipc_code
  172. btpd_common_num(struct ipc *ipc, const char *cmd, unsigned num)
  173. {
  174. struct io_buffer iob;
  175. buf_init(&iob, 16);
  176. buf_print(&iob, "l%d:%si%uee", (int)strlen(cmd), cmd, num);
  177. return ipc_buf_req(ipc, &iob);
  178. }
  179. enum ipc_code
  180. btpd_del_num(struct ipc *ipc, unsigned num)
  181. {
  182. return btpd_common_num(ipc, "del", num);
  183. }
  184. enum ipc_code
  185. btpd_start_num(struct ipc *ipc, unsigned num)
  186. {
  187. return btpd_common_num(ipc, "start", num);
  188. }
  189. enum ipc_code
  190. btpd_stop_num(struct ipc *ipc, unsigned num)
  191. {
  192. return btpd_common_num(ipc, "stop", num);
  193. }