A clone of btpd with my configuration changes.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

322 lines
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 <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. if (write_fully(ipc->sd, &qlen, sizeof(qlen)) != 0)
  102. return IPC_COMMERR;
  103. if (write_fully(ipc->sd, req, qlen) != 0)
  104. return IPC_COMMERR;
  105. if (ipc_response(ipc, res, rlen) != 0)
  106. return IPC_COMMERR;
  107. if (benc_validate(*res, *rlen) != 0)
  108. return IPC_COMMERR;
  109. if (!benc_isdct(*res))
  110. return IPC_COMMERR;
  111. return IPC_OK;
  112. }
  113. static enum ipc_err
  114. ipc_buf_req_res(struct ipc *ipc, struct io_buffer *iob, char **res,
  115. uint32_t *rlen)
  116. {
  117. enum ipc_err err;
  118. if (iob->error)
  119. err = IPC_COMMERR;
  120. else
  121. err = ipc_req_res(ipc, iob->buf, iob->off, res, rlen);
  122. buf_free(iob);
  123. return err;
  124. }
  125. static enum ipc_err
  126. ipc_buf_req_code(struct ipc *ipc, struct io_buffer *iob)
  127. {
  128. enum ipc_err err;
  129. char *res;
  130. uint32_t rlen;
  131. if ((err = ipc_buf_req_res(ipc, iob, &res, &rlen)) == 0) {
  132. err = benc_dget_int(res, "code");
  133. free(res);
  134. }
  135. return err;
  136. }
  137. enum ipc_err
  138. btpd_die(struct ipc *ipc, int seconds)
  139. {
  140. struct io_buffer iob = buf_init(16);
  141. if (seconds >= 0)
  142. buf_print(&iob, "l3:diei%dee", seconds);
  143. else
  144. buf_swrite(&iob, "l3:diee");
  145. return ipc_buf_req_code(ipc, &iob);
  146. }
  147. static enum ipc_err
  148. tget_common(char *ans, enum ipc_tval *keys, size_t nkeys, tget_cb_t cb,
  149. void *arg)
  150. {
  151. int err;
  152. const char *res;
  153. struct ipc_get_res cbres[IPC_TVALCOUNT];
  154. if ((err = benc_dget_int(ans, "code")) != 0)
  155. return err;
  156. res = benc_dget_lst(ans, "result");
  157. int obji = 0;
  158. for (res = benc_first(res); res != NULL; res = benc_next(res)) {
  159. if (benc_isint(res)) {
  160. cb(obji, benc_int(res, NULL), NULL, arg);
  161. obji++;
  162. continue;
  163. }
  164. const char *t = benc_first(res);
  165. const char *v = benc_next(t);
  166. for (int j = 0; j < nkeys; j++) {
  167. cbres[keys[j]].type = benc_int(t, NULL);
  168. switch (cbres[keys[j]].type) {
  169. case IPC_TYPE_ERR:
  170. case IPC_TYPE_NUM:
  171. cbres[keys[j]].v.num = benc_int(v, NULL);
  172. break;
  173. case IPC_TYPE_STR:
  174. case IPC_TYPE_BIN:
  175. cbres[keys[j]].v.str.p= benc_mem(v, &cbres[keys[j]].v.str.l,
  176. NULL);
  177. break;
  178. }
  179. t = benc_next(v);
  180. if (t != NULL)
  181. v = benc_next(t);
  182. }
  183. cb(obji, IPC_OK, cbres, arg);
  184. obji++;
  185. }
  186. free(ans);
  187. return IPC_OK;
  188. }
  189. enum ipc_err
  190. btpd_tget(struct ipc *ipc, struct ipc_torrent *tps, size_t ntps,
  191. enum ipc_tval *keys, size_t nkeys, tget_cb_t cb, void *arg)
  192. {
  193. char *res;
  194. uint32_t rlen;
  195. enum ipc_err err;
  196. struct io_buffer iob;
  197. if (nkeys == 0 || ntps == 0)
  198. return IPC_COMMERR;
  199. iob = buf_init(1 << 14);
  200. buf_swrite(&iob, "l4:tgetd4:froml");
  201. for (int i = 0; i < ntps; i++) {
  202. if (tps[i].by_hash) {
  203. buf_swrite(&iob, "20:");
  204. buf_write(&iob, tps[i].u.hash, 20);
  205. } else
  206. buf_print(&iob, "i%ue", tps[i].u.num);
  207. }
  208. buf_swrite(&iob, "e4:keysl");
  209. for (int k = 0; k < nkeys; k++)
  210. buf_print(&iob, "i%de", keys[k]);
  211. buf_swrite(&iob, "eee");
  212. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  213. err = tget_common(res, keys, nkeys, cb, arg);
  214. return err;
  215. }
  216. enum ipc_err
  217. btpd_tget_wc(struct ipc *ipc, enum ipc_twc twc, enum ipc_tval *keys,
  218. size_t nkeys, tget_cb_t cb, void *arg)
  219. {
  220. char *res;
  221. uint32_t rlen;
  222. struct io_buffer iob;
  223. enum ipc_err err;
  224. if (nkeys == 0)
  225. return IPC_COMMERR;
  226. iob = buf_init(1 << 14);
  227. buf_print(&iob, "l4:tgetd4:fromi%de4:keysl", twc);
  228. for (int i = 0; i < nkeys; i++)
  229. buf_print(&iob, "i%de", keys[i]);
  230. buf_swrite(&iob, "eee");
  231. if ((err = ipc_buf_req_res(ipc, &iob, &res, &rlen)) == 0)
  232. err = tget_common(res, keys, nkeys, cb, arg);
  233. return err;
  234. }
  235. enum ipc_err
  236. btpd_add(struct ipc *ipc, const char *mi, size_t mi_size, const char *content,
  237. const char *name)
  238. {
  239. struct io_buffer iob = buf_init(1 << 10);
  240. buf_print(&iob, "l3:addd7:content%d:%s", (int)strlen(content),
  241. content);
  242. if (name != NULL)
  243. buf_print(&iob, "4:name%d:%s", (int)strlen(name), name);
  244. buf_print(&iob, "7:torrent%lu:", (unsigned long)mi_size);
  245. buf_write(&iob, mi, mi_size);
  246. buf_swrite(&iob, "ee");
  247. return ipc_buf_req_code(ipc, &iob);
  248. }
  249. static enum ipc_err
  250. simple_treq(struct ipc *ipc, char *cmd, struct ipc_torrent *tp)
  251. {
  252. struct io_buffer iob = buf_init(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. }
  276. enum ipc_err
  277. btpd_stop_all(struct ipc *ipc)
  278. {
  279. struct io_buffer iob = buf_init(16);
  280. buf_swrite(&iob, "l8:stop-alle");
  281. return ipc_buf_req_code(ipc, &iob);
  282. }