A clone of btpd with my configuration changes.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

321 linhas
7.4 KiB

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <sys/un.h>
  4. #include <assert.h>
  5. #include <ctype.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. static const char *errmsgs[] = {
  20. #define ERRDEF(name, msg) msg,
  21. #include "ipcdefs.h"
  22. #undef ERRDEF
  23. NULL
  24. };
  25. static const char *tval_names[] = {
  26. #define TVDEF(val, type, name) name,
  27. #include "ipcdefs.h"
  28. #undef TVDEF
  29. NULL
  30. };
  31. const char *
  32. ipc_strerror(enum ipc_err err)
  33. {
  34. if (err < 0 || err >= IPC_ERRCOUNT)
  35. return "unknown error";
  36. return errmsgs[err];
  37. }
  38. const char *
  39. tval_name(enum ipc_tval key)
  40. {
  41. if (key < 0 || key >= IPC_TVALCOUNT)
  42. return "unknown key";
  43. return tval_names[key];
  44. }
  45. int
  46. ipc_open(const char *dir, struct ipc **out)
  47. {
  48. int sd = -1, err = 0;
  49. size_t plen;
  50. struct ipc *res;
  51. struct sockaddr_un addr;
  52. plen = sizeof(addr.sun_path);
  53. if (snprintf(addr.sun_path, plen, "%s/sock", dir) >= plen)
  54. return ENAMETOOLONG;
  55. addr.sun_family = AF_UNIX;
  56. if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
  57. return errno;
  58. if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  59. err = errno;
  60. close(sd);
  61. return err;
  62. }
  63. if ((res = malloc(sizeof(*res))) == NULL) {
  64. close(sd);
  65. return ENOMEM;
  66. }
  67. res->sd = sd;
  68. *out = res;
  69. return 0;
  70. }
  71. void
  72. ipc_close(struct ipc *ipc)
  73. {
  74. close(ipc->sd);
  75. free(ipc);
  76. }
  77. static enum ipc_err
  78. ipc_response(struct ipc *ipc, char **out, uint32_t *len)
  79. {
  80. uint32_t size;
  81. char *buf;
  82. if (read_fully(ipc->sd, &size, sizeof(size)) != 0)
  83. return IPC_COMMERR;
  84. if (size == 0)
  85. return IPC_COMMERR;
  86. if ((buf = malloc(size)) == NULL)
  87. return IPC_COMMERR;
  88. if (read_fully(ipc->sd, buf, size) != 0) {
  89. free(buf);
  90. return IPC_COMMERR;
  91. }
  92. *out = buf;
  93. *len = size;
  94. return IPC_OK;
  95. }
  96. static enum ipc_err
  97. ipc_req_res(struct ipc *ipc, const char *req, uint32_t qlen, char **res,
  98. uint32_t *rlen)
  99. {
  100. if (write_fully(ipc->sd, &qlen, sizeof(qlen)) != 0)
  101. return IPC_COMMERR;
  102. if (write_fully(ipc->sd, req, qlen) != 0)
  103. return IPC_COMMERR;
  104. if (ipc_response(ipc, res, rlen) != 0)
  105. return IPC_COMMERR;
  106. if (benc_validate(*res, *rlen) != 0)
  107. return IPC_COMMERR;
  108. if (!benc_isdct(*res))
  109. return IPC_COMMERR;
  110. return IPC_OK;
  111. }
  112. static enum ipc_err
  113. ipc_buf_req_res(struct ipc *ipc, struct iobuf *iob, char **res,
  114. uint32_t *rlen)
  115. {
  116. enum ipc_err err;
  117. if (iob->error)
  118. err = IPC_COMMERR;
  119. else
  120. err = ipc_req_res(ipc, iob->buf, iob->off, res, rlen);
  121. iobuf_free(iob);
  122. return err;
  123. }
  124. static enum ipc_err
  125. ipc_buf_req_code(struct ipc *ipc, struct iobuf *iob)
  126. {
  127. enum ipc_err err;
  128. char *res;
  129. uint32_t rlen;
  130. if ((err = ipc_buf_req_res(ipc, iob, &res, &rlen)) == 0) {
  131. err = benc_dget_int(res, "code");
  132. free(res);
  133. }
  134. return err;
  135. }
  136. enum ipc_err
  137. btpd_die(struct ipc *ipc, int seconds)
  138. {
  139. struct iobuf iob = iobuf_init(16);
  140. if (seconds >= 0)
  141. iobuf_print(&iob, "l3:diei%dee", seconds);
  142. else
  143. iobuf_swrite(&iob, "l3:diee");
  144. return ipc_buf_req_code(ipc, &iob);
  145. }
  146. static enum ipc_err
  147. tget_common(char *ans, enum ipc_tval *keys, size_t nkeys, tget_cb_t cb,
  148. void *arg)
  149. {
  150. int err;
  151. const char *res;
  152. struct ipc_get_res cbres[IPC_TVALCOUNT];
  153. if ((err = benc_dget_int(ans, "code")) != 0)
  154. return err;
  155. res = benc_dget_lst(ans, "result");
  156. int obji = 0;
  157. for (res = benc_first(res); res != NULL; res = benc_next(res)) {
  158. if (benc_isint(res)) {
  159. cb(obji, benc_int(res, NULL), NULL, arg);
  160. obji++;
  161. continue;
  162. }
  163. const char *t = benc_first(res);
  164. const char *v = benc_next(t);
  165. for (int j = 0; j < nkeys; j++) {
  166. cbres[keys[j]].type = benc_int(t, NULL);
  167. switch (cbres[keys[j]].type) {
  168. case IPC_TYPE_ERR:
  169. case IPC_TYPE_NUM:
  170. cbres[keys[j]].v.num = benc_int(v, NULL);
  171. break;
  172. case IPC_TYPE_STR:
  173. case IPC_TYPE_BIN:
  174. cbres[keys[j]].v.str.p= benc_mem(v, &cbres[keys[j]].v.str.l,
  175. NULL);
  176. break;
  177. }
  178. t = benc_next(v);
  179. if (t != NULL)
  180. v = benc_next(t);
  181. }
  182. cb(obji, IPC_OK, cbres, arg);
  183. obji++;
  184. }
  185. free(ans);
  186. return IPC_OK;
  187. }
  188. enum ipc_err
  189. btpd_tget(struct ipc *ipc, struct ipc_torrent *tps, size_t ntps,
  190. enum ipc_tval *keys, size_t nkeys, tget_cb_t cb, void *arg)
  191. {
  192. char *res;
  193. uint32_t rlen;
  194. enum ipc_err err;
  195. struct iobuf iob;
  196. if (nkeys == 0 || ntps == 0)
  197. return IPC_COMMERR;
  198. iob = iobuf_init(1 << 14);
  199. iobuf_swrite(&iob, "l4:tgetd4:froml");
  200. for (int i = 0; i < ntps; i++) {
  201. if (tps[i].by_hash) {
  202. iobuf_swrite(&iob, "20:");
  203. iobuf_write(&iob, tps[i].u.hash, 20);
  204. } else
  205. iobuf_print(&iob, "i%ue", tps[i].u.num);
  206. }
  207. iobuf_swrite(&iob, "e4:keysl");
  208. for (int k = 0; k < nkeys; k++)
  209. iobuf_print(&iob, "i%de", keys[k]);
  210. iobuf_swrite(&iob, "eee");
  211. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  212. err = tget_common(res, keys, nkeys, cb, arg);
  213. return err;
  214. }
  215. enum ipc_err
  216. btpd_tget_wc(struct ipc *ipc, enum ipc_twc twc, enum ipc_tval *keys,
  217. size_t nkeys, tget_cb_t cb, void *arg)
  218. {
  219. char *res;
  220. uint32_t rlen;
  221. struct iobuf iob;
  222. enum ipc_err err;
  223. if (nkeys == 0)
  224. return IPC_COMMERR;
  225. iob = iobuf_init(1 << 14);
  226. iobuf_print(&iob, "l4:tgetd4:fromi%de4:keysl", twc);
  227. for (int i = 0; i < nkeys; i++)
  228. iobuf_print(&iob, "i%de", keys[i]);
  229. iobuf_swrite(&iob, "eee");
  230. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  231. err = tget_common(res, keys, nkeys, cb, arg);
  232. return err;
  233. }
  234. enum ipc_err
  235. btpd_add(struct ipc *ipc, const char *mi, size_t mi_size, const char *content,
  236. const char *name)
  237. {
  238. struct iobuf iob = iobuf_init(1 << 10);
  239. iobuf_print(&iob, "l3:addd7:content%d:%s", (int)strlen(content),
  240. content);
  241. if (name != NULL)
  242. iobuf_print(&iob, "4:name%d:%s", (int)strlen(name), name);
  243. iobuf_print(&iob, "7:torrent%lu:", (unsigned long)mi_size);
  244. iobuf_write(&iob, mi, mi_size);
  245. iobuf_swrite(&iob, "ee");
  246. return ipc_buf_req_code(ipc, &iob);
  247. }
  248. static enum ipc_err
  249. simple_treq(struct ipc *ipc, char *cmd, struct ipc_torrent *tp)
  250. {
  251. struct iobuf iob = iobuf_init(32);
  252. if (tp->by_hash) {
  253. iobuf_print(&iob, "l%d:%s20:", (int)strlen(cmd), cmd);
  254. iobuf_write(&iob, tp->u.hash, 20);
  255. iobuf_swrite(&iob, "e");
  256. } else
  257. iobuf_print(&iob, "l%d:%si%uee", (int)strlen(cmd), cmd, tp->u.num);
  258. return ipc_buf_req_code(ipc, &iob);
  259. }
  260. enum ipc_err
  261. btpd_del(struct ipc *ipc, struct ipc_torrent *tp)
  262. {
  263. return simple_treq(ipc, "del", tp);
  264. }
  265. enum ipc_err
  266. btpd_start(struct ipc *ipc, struct ipc_torrent *tp)
  267. {
  268. return simple_treq(ipc, "start", tp);
  269. }
  270. enum ipc_err
  271. btpd_stop(struct ipc *ipc, struct ipc_torrent *tp)
  272. {
  273. return simple_treq(ipc, "stop", tp);
  274. }
  275. enum ipc_err
  276. btpd_stop_all(struct ipc *ipc)
  277. {
  278. struct iobuf iob = iobuf_init(16);
  279. iobuf_swrite(&iob, "l8:stop-alle");
  280. return ipc_buf_req_code(ipc, &iob);
  281. }