A clone of btpd with my configuration changes.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

336 satır
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. }