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.

321 lignes
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. }