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.

229 lignes
5.2 KiB

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