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.

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