A clone of btpd with my configuration changes.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

459 linhas
11 KiB

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <sys/time.h>
  6. #include <assert.h>
  7. #include <ctype.h>
  8. #include <errno.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <event.h>
  14. #include <evdns.h>
  15. #include "subr.h"
  16. #include "http_client.h"
  17. #define TIMEOUT (& (struct timeval) { 45, 0 })
  18. struct http_url *
  19. http_url_parse(const char *url)
  20. {
  21. size_t ulen = strlen(url);
  22. if (strncmp(url, "http://", 7) != 0)
  23. return NULL;
  24. const char *cur, *at, *uri = NULL, *uri_e = NULL;
  25. const char *host = NULL, *host_e = NULL;
  26. const char *port = NULL, *port_e = NULL;
  27. at = strchr(url + 7, '@');
  28. uri = strchr(url + 7, '/');
  29. cur = strchr(url + 7, '?');
  30. if (cur != NULL && (uri == NULL || cur < uri))
  31. uri = cur;
  32. if (uri == NULL)
  33. uri = url + ulen;
  34. if (at != NULL && at < uri)
  35. host = at + 1;
  36. else
  37. host = url + 7;
  38. cur = host;
  39. while (cur < uri && *cur != ':')
  40. cur++;
  41. host_e = cur;
  42. if (host_e == host)
  43. return NULL;
  44. if (*cur == ':') {
  45. cur++;
  46. port = cur;
  47. while (cur < uri && *cur >= '0' && *cur <= '9')
  48. cur++;
  49. if (cur == port || cur != uri)
  50. return NULL;
  51. port_e = cur;
  52. }
  53. while (*cur != '\0')
  54. cur++;
  55. uri_e = cur;
  56. struct http_url *res =
  57. malloc(sizeof(*res) + host_e - host + 1 + uri_e - uri + 2);
  58. if (res == NULL)
  59. return NULL;
  60. if (port != NULL)
  61. sscanf(port, "%hu", &res->port);
  62. else
  63. res->port = 80;
  64. res->host = (char *)(res + 1);
  65. res->uri = res->host + (host_e - host + 1);
  66. bcopy(host, res->host, host_e - host);
  67. res->host[host_e - host] = '\0';
  68. if (*uri != '/') {
  69. res->uri[0] = '/';
  70. bcopy(uri, res->uri + 1, uri_e - uri);
  71. res->uri[uri_e - uri + 1] = '\0';
  72. } else {
  73. bcopy(uri, res->uri, uri_e - uri);
  74. res->uri[uri_e - uri] = '\0';
  75. }
  76. return res;
  77. }
  78. void
  79. http_url_free(struct http_url *url)
  80. {
  81. free(url);
  82. }
  83. struct http_req {
  84. enum {
  85. HTTP_RESOLVE, HTTP_CONNECT, HTTP_WRITE, HTTP_RECEIVE, HTTP_PARSE
  86. } state;
  87. struct http_url *url;
  88. int sd;
  89. struct event ev;
  90. http_cb_t cb;
  91. void *arg;
  92. int cancel;
  93. int pstate, chunked;
  94. long length;
  95. struct evbuffer *buf;
  96. };
  97. static void
  98. http_free(struct http_req *req)
  99. {
  100. if (req->url != NULL)
  101. http_url_free(req->url);
  102. if (req->buf != NULL)
  103. evbuffer_free(req->buf);
  104. if (req->sd > 0) {
  105. event_del(&req->ev);
  106. close(req->sd);
  107. }
  108. free(req);
  109. }
  110. static void
  111. http_error(struct http_req *req)
  112. {
  113. struct http_response res;
  114. res.type = HTTP_T_ERR;
  115. res.v.error = 1;
  116. req->cb(req, &res, req->arg);
  117. http_free(req);
  118. }
  119. #define PS_HEAD 0
  120. #define PS_CHUNK_SIZE 1
  121. #define PS_CHUNK_DATA 2
  122. #define PS_CHUNK_CRLF 3
  123. #define PS_ID_DATA 4
  124. static int
  125. headers_parse(struct http_req *req, char *buf, char *end)
  126. {
  127. int code, majv, minv;
  128. char *cur, *crlf;
  129. char name[128], value[872];
  130. struct http_response res;
  131. req->chunked = 0;
  132. req->length = -1;
  133. if (sscanf(buf, "HTTP/%d.%d %d", &majv, &minv, &code) != 3)
  134. return 0;
  135. res.type = HTTP_T_CODE;
  136. res.v.code = code;
  137. req->cb(req, &res, req->arg);
  138. if (req->cancel)
  139. return 1;
  140. cur = strstr(buf, "\r\n") + 2;
  141. crlf = strstr(cur, "\r\n");
  142. while (cur < end) {
  143. int i;
  144. char *colon = strchr(cur, ':');
  145. if (colon == NULL || colon > crlf)
  146. return 0;
  147. snprintf(name, sizeof(name), "%.*s", (int)(colon - cur), cur);
  148. cur = colon + 1;
  149. i = 0;
  150. val_loop:
  151. while (isblank(*cur))
  152. cur++;
  153. while (cur < crlf) {
  154. if (i < sizeof(value) - 1) {
  155. value[i] = *cur;
  156. i++;
  157. }
  158. cur++;
  159. }
  160. cur += 2;
  161. crlf = strstr(cur, "\r\n");
  162. if (isblank(*cur)) {
  163. if (i < sizeof(value) - 1) {
  164. value[i] = ' ';
  165. i++;
  166. }
  167. cur++;
  168. goto val_loop;
  169. }
  170. value[i] = '\0';
  171. for (i--; i >= 0 && isblank(value[i]); i--)
  172. value[i] = '\0';
  173. res.type = HTTP_T_HEADER;
  174. res.v.header.n = name;
  175. res.v.header.v = value;
  176. req->cb(req, &res, req->arg);
  177. if (req->cancel)
  178. return 1;
  179. if ((!req->chunked
  180. && strcasecmp("Transfer-Encoding", name) == 0
  181. && strcasecmp("chunked", value) == 0))
  182. req->chunked = 1;
  183. if ((!req->chunked && req->length == -1
  184. && strcasecmp("Content-Length", name) == 0)) {
  185. errno = 0;
  186. req->length = strtol(value, NULL, 10);
  187. if (errno)
  188. req->length = -1;
  189. }
  190. }
  191. if (req->chunked)
  192. req->pstate = PS_CHUNK_SIZE;
  193. else
  194. req->pstate = PS_ID_DATA;
  195. return 1;
  196. }
  197. static int
  198. http_parse(struct http_req *req, int len)
  199. {
  200. char *end, *numend;
  201. size_t dlen;
  202. struct http_response res;
  203. again:
  204. switch (req->pstate) {
  205. case PS_HEAD:
  206. if (len == 0)
  207. goto error;
  208. if ((end = evbuffer_find(req->buf, "\r\n\r\n", 4)) == NULL) {
  209. if (req->buf->off < (1 << 15))
  210. return 1;
  211. else
  212. goto error;
  213. }
  214. if (evbuffer_add(req->buf, "", 1) != 0)
  215. goto error;
  216. req->buf->off--;
  217. if (!headers_parse(req, req->buf->buffer, end))
  218. goto error;
  219. if (req->cancel)
  220. goto cancel;
  221. evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 4);
  222. goto again;
  223. case PS_CHUNK_SIZE:
  224. assert(req->chunked);
  225. if (len == 0)
  226. goto error;
  227. if ((end = evbuffer_find(req->buf, "\r\n", 2)) == NULL) {
  228. if (req->buf->off < 20)
  229. return 1;
  230. else
  231. goto error;
  232. }
  233. errno = 0;
  234. req->length = strtol(req->buf->buffer, &numend, 16);
  235. if (req->length < 0 || numend == (char *)req->buf->buffer || errno)
  236. goto error;
  237. if (req->length == 0)
  238. goto done;
  239. evbuffer_drain(req->buf, end - (char *)req->buf->buffer + 2);
  240. req->pstate = PS_CHUNK_DATA;
  241. goto again;
  242. case PS_CHUNK_DATA:
  243. if (len == 0)
  244. goto error;
  245. assert(req->length > 0);
  246. dlen = min(req->buf->off, req->length);
  247. if (dlen > 0) {
  248. res.type = HTTP_T_DATA;
  249. res.v.data.l = dlen;
  250. res.v.data.p = req->buf->buffer;
  251. req->cb(req, &res, req->arg);
  252. if (req->cancel)
  253. goto cancel;
  254. evbuffer_drain(req->buf, dlen);
  255. req->length -= dlen;
  256. if (req->length == 0) {
  257. req->pstate = PS_CHUNK_CRLF;
  258. goto again;
  259. }
  260. }
  261. return 1;
  262. case PS_CHUNK_CRLF:
  263. if (len == 0)
  264. goto error;
  265. assert(req->length == 0);
  266. if (req->buf->off < 2)
  267. return 1;
  268. if (bcmp(req->buf->buffer, "\r\n", 2) != 0)
  269. goto error;
  270. evbuffer_drain(req->buf, 2);
  271. req->pstate = PS_CHUNK_SIZE;
  272. goto again;
  273. case PS_ID_DATA:
  274. if (len == 0 && req->length < 0)
  275. goto done;
  276. else if (len == 0)
  277. goto error;
  278. if (req->length < 0)
  279. dlen = req->buf->off;
  280. else
  281. dlen = min(req->buf->off, req->length);
  282. if (dlen > 0) {
  283. res.type = HTTP_T_DATA;
  284. res.v.data.p = req->buf->buffer;
  285. res.v.data.l = dlen;
  286. req->cb(req, &res, req->arg);
  287. if (req->cancel)
  288. goto cancel;
  289. evbuffer_drain(req->buf, dlen);
  290. if (req->length > 0) {
  291. req->length -= dlen;
  292. if (req->length == 0)
  293. goto done;
  294. }
  295. }
  296. return 1;
  297. default:
  298. abort();
  299. }
  300. error:
  301. http_error(req);
  302. return 0;
  303. done:
  304. res.type = HTTP_T_DONE;
  305. req->cb(req, &res, req->arg);
  306. cancel:
  307. http_free(req);
  308. return 0;
  309. }
  310. static void
  311. http_read_cb(int sd, short type, void *arg)
  312. {
  313. struct http_req *req = arg;
  314. if (type == EV_TIMEOUT) {
  315. http_error(req);
  316. return;
  317. }
  318. int nr = evbuffer_read(req->buf, sd, 1 << 14);
  319. if (nr < 0) {
  320. if (nr == EAGAIN)
  321. goto more;
  322. else {
  323. printf("read err\n");
  324. http_error(req);
  325. return;
  326. }
  327. }
  328. req->state = HTTP_PARSE;
  329. if (!http_parse(req, nr))
  330. return;
  331. req->state = HTTP_RECEIVE;
  332. more:
  333. if (event_add(&req->ev, TIMEOUT) != 0)
  334. http_error(req);
  335. }
  336. static void
  337. http_write_cb(int sd, short type, void *arg)
  338. {
  339. struct http_req *req = arg;
  340. if (type == EV_TIMEOUT) {
  341. http_error(req);
  342. return;
  343. }
  344. int nw = evbuffer_write(req->buf, sd);
  345. if (nw == -1) {
  346. if (errno == EAGAIN)
  347. goto out;
  348. else
  349. goto error;
  350. }
  351. out:
  352. if (req->buf->off != 0) {
  353. if (event_add(&req->ev, TIMEOUT) != 0)
  354. goto error;
  355. } else {
  356. req->state = HTTP_RECEIVE;
  357. event_set(&req->ev, req->sd, EV_READ, http_read_cb, req);
  358. if (event_add(&req->ev, TIMEOUT) != 0)
  359. goto error;
  360. }
  361. return;
  362. error:
  363. printf("http write err\n");
  364. http_error(req);
  365. }
  366. static void
  367. http_dnscb(int result, char type, int count, int ttl, void *addrs, void *arg)
  368. {
  369. struct http_req *req = arg;
  370. if (req->cancel)
  371. http_free(req);
  372. else if (result == 0 && type == 1 && count > 0) {
  373. int addri = rand_between(0, count - 1);
  374. struct sockaddr_in addr;
  375. addr.sin_family = AF_INET;
  376. addr.sin_port = htons(req->url->port);
  377. bcopy(addrs + addri * 4, &addr.sin_addr.s_addr, 4);
  378. req->state = HTTP_CONNECT;
  379. if ((req->sd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
  380. goto error;
  381. if (set_nonblocking(req->sd) != 0)
  382. goto error;
  383. if ((connect(req->sd, (struct sockaddr *)&addr, sizeof(addr)) != 0
  384. && errno != EINPROGRESS))
  385. goto error;
  386. event_set(&req->ev, req->sd, EV_WRITE, http_write_cb, req);
  387. if (event_add(&req->ev, TIMEOUT) != 0)
  388. goto error;
  389. } else
  390. goto error;
  391. return;
  392. error:
  393. http_error(req);
  394. }
  395. int
  396. http_get(struct http_req **out, const char *url, const char *hdrs,
  397. http_cb_t cb, void *arg)
  398. {
  399. struct http_req *req = calloc(1, sizeof(*req));
  400. if (req == NULL)
  401. return 0;
  402. req->sd = -1;
  403. req->cb = cb;
  404. req->arg = arg;
  405. req->url = http_url_parse(url);
  406. if (req->url == NULL)
  407. goto error;
  408. if ((req->buf = evbuffer_new()) == NULL)
  409. goto error;
  410. if (evbuffer_add_printf(req->buf, "GET %s HTTP/1.1\r\n"
  411. "Accept-Encoding:\r\n"
  412. "Connection: close\r\n"
  413. "Host: %s\r\n"
  414. "%s"
  415. "\r\n", req->url->uri, req->url->host, hdrs) == -1)
  416. goto error;
  417. if (evdns_resolve_ipv4(req->url->host, 0, http_dnscb, req) != 0)
  418. goto error;
  419. if (out != NULL)
  420. *out = req;
  421. return 1;
  422. error:
  423. http_free(req);
  424. return 0;
  425. }
  426. void
  427. http_cancel(struct http_req *req)
  428. {
  429. if (req->state == HTTP_RESOLVE || req->state == HTTP_PARSE)
  430. req->cancel = 1;
  431. else
  432. http_free(req);
  433. }