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.

336 lignes
7.7 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)
  138. {
  139. struct iobuf iob = iobuf_init(16);
  140. iobuf_swrite(&iob, "l3:diee");
  141. return ipc_buf_req_code(ipc, &iob);
  142. }
  143. static enum ipc_err
  144. tget_common(char *ans, enum ipc_tval *keys, size_t nkeys, tget_cb_t cb,
  145. void *arg)
  146. {
  147. int err;
  148. const char *res;
  149. struct ipc_get_res cbres[IPC_TVALCOUNT];
  150. if ((err = benc_dget_int(ans, "code")) != 0)
  151. return err;
  152. res = benc_dget_lst(ans, "result");
  153. int obji = 0;
  154. for (res = benc_first(res); res != NULL; res = benc_next(res)) {
  155. if (benc_isint(res)) {
  156. cb(obji, benc_int(res, NULL), NULL, arg);
  157. obji++;
  158. continue;
  159. }
  160. const char *t = benc_first(res);
  161. const char *v = benc_next(t);
  162. for (int j = 0; j < nkeys; j++) {
  163. cbres[keys[j]].type = benc_int(t, NULL);
  164. switch (cbres[keys[j]].type) {
  165. case IPC_TYPE_ERR:
  166. case IPC_TYPE_NUM:
  167. cbres[keys[j]].v.num = benc_int(v, NULL);
  168. break;
  169. case IPC_TYPE_STR:
  170. case IPC_TYPE_BIN:
  171. cbres[keys[j]].v.str.p= benc_mem(v, &cbres[keys[j]].v.str.l,
  172. NULL);
  173. break;
  174. }
  175. t = benc_next(v);
  176. if (t != NULL)
  177. v = benc_next(t);
  178. }
  179. cb(obji, IPC_OK, cbres, arg);
  180. obji++;
  181. }
  182. free(ans);
  183. return IPC_OK;
  184. }
  185. enum ipc_err
  186. btpd_tget(struct ipc *ipc, struct ipc_torrent *tps, size_t ntps,
  187. enum ipc_tval *keys, size_t nkeys, tget_cb_t cb, void *arg)
  188. {
  189. char *res;
  190. uint32_t rlen;
  191. enum ipc_err err;
  192. struct iobuf iob;
  193. if (nkeys == 0 || ntps == 0)
  194. return IPC_COMMERR;
  195. iob = iobuf_init(1 << 14);
  196. iobuf_swrite(&iob, "l4:tgetd4:froml");
  197. for (int i = 0; i < ntps; i++) {
  198. if (tps[i].by_hash) {
  199. iobuf_swrite(&iob, "20:");
  200. iobuf_write(&iob, tps[i].u.hash, 20);
  201. } else
  202. iobuf_print(&iob, "i%ue", tps[i].u.num);
  203. }
  204. iobuf_swrite(&iob, "e4:keysl");
  205. for (int k = 0; k < nkeys; k++)
  206. iobuf_print(&iob, "i%de", keys[k]);
  207. iobuf_swrite(&iob, "eee");
  208. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  209. err = tget_common(res, keys, nkeys, cb, arg);
  210. return err;
  211. }
  212. enum ipc_err
  213. btpd_tget_wc(struct ipc *ipc, enum ipc_twc twc, enum ipc_tval *keys,
  214. size_t nkeys, tget_cb_t cb, void *arg)
  215. {
  216. char *res;
  217. uint32_t rlen;
  218. struct iobuf iob;
  219. enum ipc_err err;
  220. if (nkeys == 0)
  221. return IPC_COMMERR;
  222. iob = iobuf_init(1 << 14);
  223. iobuf_print(&iob, "l4:tgetd4:fromi%de4:keysl", twc);
  224. for (int i = 0; i < nkeys; i++)
  225. iobuf_print(&iob, "i%de", keys[i]);
  226. iobuf_swrite(&iob, "eee");
  227. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  228. err = tget_common(res, keys, nkeys, cb, arg);
  229. return err;
  230. }
  231. enum ipc_err
  232. btpd_add(struct ipc *ipc, const char *mi, size_t mi_size, const char *content,
  233. const char *name, const char *label)
  234. {
  235. struct iobuf iob = iobuf_init(1 << 10);
  236. iobuf_print(&iob, "l3:addd7:content%d:%s", (int)strlen(content),
  237. content);
  238. if (name != NULL)
  239. iobuf_print(&iob, "4:name%d:%s", (int)strlen(name), name);
  240. if (label != NULL)
  241. iobuf_print(&iob, "5:label%d:%s", (int)strlen(label), label);
  242. iobuf_print(&iob, "7:torrent%lu:", (unsigned long)mi_size);
  243. iobuf_write(&iob, mi, mi_size);
  244. iobuf_swrite(&iob, "ee");
  245. return ipc_buf_req_code(ipc, &iob);
  246. }
  247. static enum ipc_err
  248. simple_treq(struct ipc *ipc, char *cmd, struct ipc_torrent *tp)
  249. {
  250. struct iobuf iob = iobuf_init(32);
  251. if (tp->by_hash) {
  252. iobuf_print(&iob, "l%d:%s20:", (int)strlen(cmd), cmd);
  253. iobuf_write(&iob, tp->u.hash, 20);
  254. iobuf_swrite(&iob, "e");
  255. } else
  256. iobuf_print(&iob, "l%d:%si%uee", (int)strlen(cmd), cmd, tp->u.num);
  257. return ipc_buf_req_code(ipc, &iob);
  258. }
  259. enum ipc_err
  260. btpd_del(struct ipc *ipc, struct ipc_torrent *tp)
  261. {
  262. return simple_treq(ipc, "del", tp);
  263. }
  264. enum ipc_err
  265. btpd_rate(struct ipc *ipc, unsigned up, unsigned down)
  266. {
  267. struct iobuf iob = iobuf_init(32);
  268. iobuf_print(&iob, "l4:ratei%iei%iee", up, down);
  269. return ipc_buf_req_code(ipc, &iob);
  270. }
  271. enum ipc_err
  272. btpd_start(struct ipc *ipc, struct ipc_torrent *tp)
  273. {
  274. return simple_treq(ipc, "start", tp);
  275. }
  276. enum ipc_err
  277. btpd_start_all(struct ipc *ipc)
  278. {
  279. struct iobuf iob = iobuf_init(16);
  280. iobuf_swrite(&iob, "l9:start-alle");
  281. return ipc_buf_req_code(ipc, &iob);
  282. }
  283. enum ipc_err
  284. btpd_stop(struct ipc *ipc, struct ipc_torrent *tp)
  285. {
  286. return simple_treq(ipc, "stop", tp);
  287. }
  288. enum ipc_err
  289. btpd_stop_all(struct ipc *ipc)
  290. {
  291. struct iobuf iob = iobuf_init(16);
  292. iobuf_swrite(&iob, "l8:stop-alle");
  293. return ipc_buf_req_code(ipc, &iob);
  294. }