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.

пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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)
  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. iobuf_print(&iob, "7:torrent%lu:", (unsigned long)mi_size);
  241. iobuf_write(&iob, mi, mi_size);
  242. iobuf_swrite(&iob, "ee");
  243. return ipc_buf_req_code(ipc, &iob);
  244. }
  245. static enum ipc_err
  246. simple_treq(struct ipc *ipc, char *cmd, struct ipc_torrent *tp)
  247. {
  248. struct iobuf iob = iobuf_init(32);
  249. if (tp->by_hash) {
  250. iobuf_print(&iob, "l%d:%s20:", (int)strlen(cmd), cmd);
  251. iobuf_write(&iob, tp->u.hash, 20);
  252. iobuf_swrite(&iob, "e");
  253. } else
  254. iobuf_print(&iob, "l%d:%si%uee", (int)strlen(cmd), cmd, tp->u.num);
  255. return ipc_buf_req_code(ipc, &iob);
  256. }
  257. enum ipc_err
  258. btpd_del(struct ipc *ipc, struct ipc_torrent *tp)
  259. {
  260. return simple_treq(ipc, "del", tp);
  261. }
  262. enum ipc_err
  263. btpd_start(struct ipc *ipc, struct ipc_torrent *tp)
  264. {
  265. return simple_treq(ipc, "start", tp);
  266. }
  267. enum ipc_err
  268. btpd_stop(struct ipc *ipc, struct ipc_torrent *tp)
  269. {
  270. return simple_treq(ipc, "stop", tp);
  271. }
  272. enum ipc_err
  273. btpd_stop_all(struct ipc *ipc)
  274. {
  275. struct iobuf iob = iobuf_init(16);
  276. iobuf_swrite(&iob, "l8:stop-alle");
  277. return ipc_buf_req_code(ipc, &iob);
  278. }