A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

btpd_if.c 7.4 KiB

18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
18 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. }