httpread.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * httpread - Manage reading file(s) from HTTP/TCP socket
  3. * Author: Ted Merrill
  4. * Copyright 2008 Atheros Communications
  5. *
  6. * This software may be distributed under the terms of the BSD license.
  7. * See README for more details.
  8. *
  9. * The files are buffered via internal callbacks from eloop, then presented to
  10. * an application callback routine when completely read into memory. May also
  11. * be used if no file is expected but just to get the header, including HTTP
  12. * replies (e.g. HTTP/1.1 200 OK etc.).
  13. *
  14. * This does not attempt to be an optimally efficient implementation, but does
  15. * attempt to be of reasonably small size and memory consumption; assuming that
  16. * only small files are to be read. A maximum file size is provided by
  17. * application and enforced.
  18. *
  19. * It is assumed that the application does not expect any of the following:
  20. * -- transfer encoding other than chunked
  21. * -- trailer fields
  22. * It is assumed that, even if the other side requested that the connection be
  23. * kept open, that we will close it (thus HTTP messages sent by application
  24. * should have the connection closed field); this is allowed by HTTP/1.1 and
  25. * simplifies things for us.
  26. *
  27. * Other limitations:
  28. * -- HTTP header may not exceed a hard-coded size.
  29. *
  30. * Notes:
  31. * This code would be massively simpler without some of the new features of
  32. * HTTP/1.1, especially chunked data.
  33. */
  34. #include "includes.h"
  35. #include "common.h"
  36. #include "eloop.h"
  37. #include "httpread.h"
  38. /* Tunable parameters */
  39. #define HTTPREAD_READBUF_SIZE 1024 /* read in chunks of this size */
  40. #define HTTPREAD_HEADER_MAX_SIZE 4096 /* max allowed for headers */
  41. #define HTTPREAD_BODYBUF_DELTA 4096 /* increase allocation by this */
  42. #if 0
  43. /* httpread_debug -- set this global variable > 0 e.g. from debugger
  44. * to enable debugs (larger numbers for more debugs)
  45. * Make this a #define of 0 to eliminate the debugging code.
  46. */
  47. int httpread_debug = 99;
  48. #else
  49. #define httpread_debug 0 /* eliminates even the debugging code */
  50. #endif
  51. /* control instance -- actual definition (opaque to application)
  52. */
  53. struct httpread {
  54. /* information from creation */
  55. int sd; /* descriptor of TCP socket to read from */
  56. void (*cb)(struct httpread *handle, void *cookie,
  57. enum httpread_event e); /* call on event */
  58. void *cookie; /* pass to callback */
  59. int max_bytes; /* maximum file size else abort it */
  60. int timeout_seconds; /* 0 or total duration timeout period */
  61. /* dynamically used information follows */
  62. int got_hdr; /* nonzero when header is finalized */
  63. char hdr[HTTPREAD_HEADER_MAX_SIZE+1]; /* headers stored here */
  64. int hdr_nbytes;
  65. enum httpread_hdr_type hdr_type;
  66. int version; /* 1 if we've seen 1.1 */
  67. int reply_code; /* for type REPLY, e.g. 200 for HTTP/1.1 200 OK */
  68. int got_content_length; /* true if we know content length for sure */
  69. int content_length; /* body length, iff got_content_length */
  70. int chunked; /* nonzero for chunked data */
  71. char *uri;
  72. int got_body; /* nonzero when body is finalized */
  73. char *body;
  74. int body_nbytes;
  75. int body_alloc_nbytes; /* amount allocated */
  76. int got_file; /* here when we are done */
  77. /* The following apply if data is chunked: */
  78. int in_chunk_data; /* 0=in/at header, 1=in the data or tail*/
  79. int chunk_start; /* offset in body of chunk hdr or data */
  80. int chunk_size; /* data of chunk (not hdr or ending CRLF)*/
  81. int in_trailer; /* in header fields after data (chunked only)*/
  82. enum trailer_state {
  83. trailer_line_begin = 0,
  84. trailer_empty_cr, /* empty line + CR */
  85. trailer_nonempty,
  86. trailer_nonempty_cr,
  87. } trailer_state;
  88. };
  89. /* Check words for equality, where words consist of graphical characters
  90. * delimited by whitespace
  91. * Returns nonzero if "equal" doing case insensitive comparison.
  92. */
  93. static int word_eq(char *s1, char *s2)
  94. {
  95. int c1;
  96. int c2;
  97. int end1 = 0;
  98. int end2 = 0;
  99. for (;;) {
  100. c1 = *s1++;
  101. c2 = *s2++;
  102. if (isalpha(c1) && isupper(c1))
  103. c1 = tolower(c1);
  104. if (isalpha(c2) && isupper(c2))
  105. c2 = tolower(c2);
  106. end1 = !isgraph(c1);
  107. end2 = !isgraph(c2);
  108. if (end1 || end2 || c1 != c2)
  109. break;
  110. }
  111. return end1 && end2; /* reached end of both words? */
  112. }
  113. static void httpread_timeout_handler(void *eloop_data, void *user_ctx);
  114. /* httpread_destroy -- if h is non-NULL, clean up
  115. * This must eventually be called by the application following
  116. * call of the application's callback and may be called
  117. * earlier if desired.
  118. */
  119. void httpread_destroy(struct httpread *h)
  120. {
  121. if (httpread_debug >= 10)
  122. wpa_printf(MSG_DEBUG, "ENTER httpread_destroy(%p)", h);
  123. if (!h)
  124. return;
  125. eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
  126. eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
  127. os_free(h->body);
  128. os_free(h->uri);
  129. os_memset(h, 0, sizeof(*h)); /* aid debugging */
  130. h->sd = -1; /* aid debugging */
  131. os_free(h);
  132. }
  133. /* httpread_timeout_handler -- called on excessive total duration
  134. */
  135. static void httpread_timeout_handler(void *eloop_data, void *user_ctx)
  136. {
  137. struct httpread *h = user_ctx;
  138. wpa_printf(MSG_DEBUG, "httpread timeout (%p)", h);
  139. (*h->cb)(h, h->cookie, HTTPREAD_EVENT_TIMEOUT);
  140. }
  141. /* Analyze options only so far as is needed to correctly obtain the file.
  142. * The application can look at the raw header to find other options.
  143. */
  144. static int httpread_hdr_option_analyze(
  145. struct httpread *h,
  146. char *hbp /* pointer to current line in header buffer */
  147. )
  148. {
  149. if (word_eq(hbp, "CONTENT-LENGTH:")) {
  150. while (isgraph(*hbp))
  151. hbp++;
  152. while (*hbp == ' ' || *hbp == '\t')
  153. hbp++;
  154. if (!isdigit(*hbp))
  155. return -1;
  156. h->content_length = atol(hbp);
  157. h->got_content_length = 1;
  158. return 0;
  159. }
  160. if (word_eq(hbp, "TRANSFER_ENCODING:") ||
  161. word_eq(hbp, "TRANSFER-ENCODING:")) {
  162. while (isgraph(*hbp))
  163. hbp++;
  164. while (*hbp == ' ' || *hbp == '\t')
  165. hbp++;
  166. /* There should (?) be no encodings of interest
  167. * other than chunked...
  168. */
  169. if (word_eq(hbp, "CHUNKED")) {
  170. h->chunked = 1;
  171. h->in_chunk_data = 0;
  172. /* ignore possible ;<parameters> */
  173. }
  174. return 0;
  175. }
  176. /* skip anything we don't know, which is a lot */
  177. return 0;
  178. }
  179. static int httpread_hdr_analyze(struct httpread *h)
  180. {
  181. char *hbp = h->hdr; /* pointer into h->hdr */
  182. int standard_first_line = 1;
  183. /* First line is special */
  184. h->hdr_type = HTTPREAD_HDR_TYPE_UNKNOWN;
  185. if (!isgraph(*hbp))
  186. goto bad;
  187. if (os_strncmp(hbp, "HTTP/", 5) == 0) {
  188. h->hdr_type = HTTPREAD_HDR_TYPE_REPLY;
  189. standard_first_line = 0;
  190. hbp += 5;
  191. if (hbp[0] == '1' && hbp[1] == '.' &&
  192. isdigit(hbp[2]) && hbp[2] != '0')
  193. h->version = 1;
  194. while (isgraph(*hbp))
  195. hbp++;
  196. while (*hbp == ' ' || *hbp == '\t')
  197. hbp++;
  198. if (!isdigit(*hbp))
  199. goto bad;
  200. h->reply_code = atol(hbp);
  201. } else if (word_eq(hbp, "GET"))
  202. h->hdr_type = HTTPREAD_HDR_TYPE_GET;
  203. else if (word_eq(hbp, "HEAD"))
  204. h->hdr_type = HTTPREAD_HDR_TYPE_HEAD;
  205. else if (word_eq(hbp, "POST"))
  206. h->hdr_type = HTTPREAD_HDR_TYPE_POST;
  207. else if (word_eq(hbp, "PUT"))
  208. h->hdr_type = HTTPREAD_HDR_TYPE_PUT;
  209. else if (word_eq(hbp, "DELETE"))
  210. h->hdr_type = HTTPREAD_HDR_TYPE_DELETE;
  211. else if (word_eq(hbp, "TRACE"))
  212. h->hdr_type = HTTPREAD_HDR_TYPE_TRACE;
  213. else if (word_eq(hbp, "CONNECT"))
  214. h->hdr_type = HTTPREAD_HDR_TYPE_CONNECT;
  215. else if (word_eq(hbp, "NOTIFY"))
  216. h->hdr_type = HTTPREAD_HDR_TYPE_NOTIFY;
  217. else if (word_eq(hbp, "M-SEARCH"))
  218. h->hdr_type = HTTPREAD_HDR_TYPE_M_SEARCH;
  219. else if (word_eq(hbp, "M-POST"))
  220. h->hdr_type = HTTPREAD_HDR_TYPE_M_POST;
  221. else if (word_eq(hbp, "SUBSCRIBE"))
  222. h->hdr_type = HTTPREAD_HDR_TYPE_SUBSCRIBE;
  223. else if (word_eq(hbp, "UNSUBSCRIBE"))
  224. h->hdr_type = HTTPREAD_HDR_TYPE_UNSUBSCRIBE;
  225. else {
  226. }
  227. if (standard_first_line) {
  228. char *rawuri;
  229. char *uri;
  230. /* skip type */
  231. while (isgraph(*hbp))
  232. hbp++;
  233. while (*hbp == ' ' || *hbp == '\t')
  234. hbp++;
  235. /* parse uri.
  236. * Find length, allocate memory for translated
  237. * copy, then translate by changing %<hex><hex>
  238. * into represented value.
  239. */
  240. rawuri = hbp;
  241. while (isgraph(*hbp))
  242. hbp++;
  243. h->uri = os_malloc((hbp - rawuri) + 1);
  244. if (h->uri == NULL)
  245. goto bad;
  246. uri = h->uri;
  247. while (rawuri < hbp) {
  248. int c = *rawuri;
  249. if (c == '%' &&
  250. isxdigit(rawuri[1]) && isxdigit(rawuri[2])) {
  251. *uri++ = hex2byte(rawuri + 1);
  252. rawuri += 3;
  253. } else {
  254. *uri++ = c;
  255. rawuri++;
  256. }
  257. }
  258. *uri = 0; /* null terminate */
  259. while (isgraph(*hbp))
  260. hbp++;
  261. while (*hbp == ' ' || *hbp == '\t')
  262. hbp++;
  263. /* get version */
  264. if (0 == strncmp(hbp, "HTTP/", 5)) {
  265. hbp += 5;
  266. if (hbp[0] == '1' && hbp[1] == '.' &&
  267. isdigit(hbp[2]) && hbp[2] != '0')
  268. h->version = 1;
  269. }
  270. }
  271. /* skip rest of line */
  272. while (*hbp)
  273. if (*hbp++ == '\n')
  274. break;
  275. /* Remainder of lines are options, in any order;
  276. * or empty line to terminate
  277. */
  278. for (;;) {
  279. /* Empty line to terminate */
  280. if (hbp[0] == '\n' ||
  281. (hbp[0] == '\r' && hbp[1] == '\n'))
  282. break;
  283. if (!isgraph(*hbp))
  284. goto bad;
  285. if (httpread_hdr_option_analyze(h, hbp))
  286. goto bad;
  287. /* skip line */
  288. while (*hbp)
  289. if (*hbp++ == '\n')
  290. break;
  291. }
  292. /* chunked overrides content-length always */
  293. if (h->chunked)
  294. h->got_content_length = 0;
  295. /* For some types, we should not try to read a body
  296. * This is in addition to the application determining
  297. * that we should not read a body.
  298. */
  299. switch (h->hdr_type) {
  300. case HTTPREAD_HDR_TYPE_REPLY:
  301. /* Some codes can have a body and some not.
  302. * For now, just assume that any other than 200
  303. * do not...
  304. */
  305. if (h->reply_code != 200)
  306. h->max_bytes = 0;
  307. break;
  308. case HTTPREAD_HDR_TYPE_GET:
  309. case HTTPREAD_HDR_TYPE_HEAD:
  310. /* in practice it appears that it is assumed
  311. * that GETs have a body length of 0... ?
  312. */
  313. if (h->chunked == 0 && h->got_content_length == 0)
  314. h->max_bytes = 0;
  315. break;
  316. case HTTPREAD_HDR_TYPE_POST:
  317. case HTTPREAD_HDR_TYPE_PUT:
  318. case HTTPREAD_HDR_TYPE_DELETE:
  319. case HTTPREAD_HDR_TYPE_TRACE:
  320. case HTTPREAD_HDR_TYPE_CONNECT:
  321. case HTTPREAD_HDR_TYPE_NOTIFY:
  322. case HTTPREAD_HDR_TYPE_M_SEARCH:
  323. case HTTPREAD_HDR_TYPE_M_POST:
  324. case HTTPREAD_HDR_TYPE_SUBSCRIBE:
  325. case HTTPREAD_HDR_TYPE_UNSUBSCRIBE:
  326. default:
  327. break;
  328. }
  329. return 0;
  330. bad:
  331. /* Error */
  332. return -1;
  333. }
  334. /* httpread_read_handler -- called when socket ready to read
  335. *
  336. * Note: any extra data we read past end of transmitted file is ignored;
  337. * if we were to support keeping connections open for multiple files then
  338. * this would have to be addressed.
  339. */
  340. static void httpread_read_handler(int sd, void *eloop_ctx, void *sock_ctx)
  341. {
  342. struct httpread *h = sock_ctx;
  343. int nread;
  344. char *rbp; /* pointer into read buffer */
  345. char *hbp; /* pointer into header buffer */
  346. char *bbp; /* pointer into body buffer */
  347. char readbuf[HTTPREAD_READBUF_SIZE]; /* temp use to read into */
  348. if (httpread_debug >= 20)
  349. wpa_printf(MSG_DEBUG, "ENTER httpread_read_handler(%p)", h);
  350. /* read some at a time, then search for the interal
  351. * boundaries between header and data and etc.
  352. */
  353. nread = read(h->sd, readbuf, sizeof(readbuf));
  354. if (nread < 0)
  355. goto bad;
  356. if (nread == 0) {
  357. /* end of transmission... this may be normal
  358. * or may be an error... in some cases we can't
  359. * tell which so we must assume it is normal then.
  360. */
  361. if (!h->got_hdr) {
  362. /* Must at least have completed header */
  363. wpa_printf(MSG_DEBUG, "httpread premature eof(%p)", h);
  364. goto bad;
  365. }
  366. if (h->chunked || h->got_content_length) {
  367. /* Premature EOF; e.g. dropped connection */
  368. wpa_printf(MSG_DEBUG,
  369. "httpread premature eof(%p) %d/%d",
  370. h, h->body_nbytes,
  371. h->content_length);
  372. goto bad;
  373. }
  374. /* No explicit length, hopefully we have all the data
  375. * although dropped connections can cause false
  376. * end
  377. */
  378. if (httpread_debug >= 10)
  379. wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h);
  380. h->got_body = 1;
  381. goto got_file;
  382. }
  383. rbp = readbuf;
  384. /* Header consists of text lines (terminated by both CR and LF)
  385. * and an empty line (CR LF only).
  386. */
  387. if (!h->got_hdr) {
  388. hbp = h->hdr + h->hdr_nbytes;
  389. /* add to headers until:
  390. * -- we run out of data in read buffer
  391. * -- or, we run out of header buffer room
  392. * -- or, we get double CRLF in headers
  393. */
  394. for (;;) {
  395. if (nread == 0)
  396. goto get_more;
  397. if (h->hdr_nbytes == HTTPREAD_HEADER_MAX_SIZE) {
  398. goto bad;
  399. }
  400. *hbp++ = *rbp++;
  401. nread--;
  402. h->hdr_nbytes++;
  403. if (h->hdr_nbytes >= 4 &&
  404. hbp[-1] == '\n' &&
  405. hbp[-2] == '\r' &&
  406. hbp[-3] == '\n' &&
  407. hbp[-4] == '\r' ) {
  408. h->got_hdr = 1;
  409. *hbp = 0; /* null terminate */
  410. break;
  411. }
  412. }
  413. /* here we've just finished reading the header */
  414. if (httpread_hdr_analyze(h)) {
  415. wpa_printf(MSG_DEBUG, "httpread bad hdr(%p)", h);
  416. goto bad;
  417. }
  418. if (h->max_bytes == 0) {
  419. if (httpread_debug >= 10)
  420. wpa_printf(MSG_DEBUG,
  421. "httpread no body hdr end(%p)", h);
  422. goto got_file;
  423. }
  424. if (h->got_content_length && h->content_length == 0) {
  425. if (httpread_debug >= 10)
  426. wpa_printf(MSG_DEBUG,
  427. "httpread zero content length(%p)",
  428. h);
  429. goto got_file;
  430. }
  431. }
  432. /* Certain types of requests never have data and so
  433. * must be specially recognized.
  434. */
  435. if (!os_strncasecmp(h->hdr, "SUBSCRIBE", 9) ||
  436. !os_strncasecmp(h->hdr, "UNSUBSCRIBE", 11) ||
  437. !os_strncasecmp(h->hdr, "HEAD", 4) ||
  438. !os_strncasecmp(h->hdr, "GET", 3)) {
  439. if (!h->got_body) {
  440. if (httpread_debug >= 10)
  441. wpa_printf(MSG_DEBUG,
  442. "httpread NO BODY for sp. type");
  443. }
  444. h->got_body = 1;
  445. goto got_file;
  446. }
  447. /* Data can be just plain binary data, or if "chunked"
  448. * consists of chunks each with a header, ending with
  449. * an ending header.
  450. */
  451. if (nread == 0)
  452. goto get_more;
  453. if (!h->got_body) {
  454. /* Here to get (more of) body */
  455. /* ensure we have enough room for worst case for body
  456. * plus a null termination character
  457. */
  458. if (h->body_alloc_nbytes < (h->body_nbytes + nread + 1)) {
  459. char *new_body;
  460. int new_alloc_nbytes;
  461. if (h->body_nbytes >= h->max_bytes)
  462. goto bad;
  463. new_alloc_nbytes = h->body_alloc_nbytes +
  464. HTTPREAD_BODYBUF_DELTA;
  465. /* For content-length case, the first time
  466. * through we allocate the whole amount
  467. * we need.
  468. */
  469. if (h->got_content_length &&
  470. new_alloc_nbytes < (h->content_length + 1))
  471. new_alloc_nbytes = h->content_length + 1;
  472. if ((new_body = os_realloc(h->body, new_alloc_nbytes))
  473. == NULL)
  474. goto bad;
  475. h->body = new_body;
  476. h->body_alloc_nbytes = new_alloc_nbytes;
  477. }
  478. /* add bytes */
  479. bbp = h->body + h->body_nbytes;
  480. for (;;) {
  481. int ncopy;
  482. /* See if we need to stop */
  483. if (h->chunked && h->in_chunk_data == 0) {
  484. /* in chunk header */
  485. char *cbp = h->body + h->chunk_start;
  486. if (bbp-cbp >= 2 && bbp[-2] == '\r' &&
  487. bbp[-1] == '\n') {
  488. /* end of chunk hdr line */
  489. /* hdr line consists solely
  490. * of a hex numeral and CFLF
  491. */
  492. if (!isxdigit(*cbp))
  493. goto bad;
  494. h->chunk_size = strtoul(cbp, NULL, 16);
  495. /* throw away chunk header
  496. * so we have only real data
  497. */
  498. h->body_nbytes = h->chunk_start;
  499. bbp = cbp;
  500. if (h->chunk_size == 0) {
  501. /* end of chunking */
  502. /* trailer follows */
  503. h->in_trailer = 1;
  504. if (httpread_debug >= 20)
  505. wpa_printf(
  506. MSG_DEBUG,
  507. "httpread end chunks(%p)", h);
  508. break;
  509. }
  510. h->in_chunk_data = 1;
  511. /* leave chunk_start alone */
  512. }
  513. } else if (h->chunked) {
  514. /* in chunk data */
  515. if ((h->body_nbytes - h->chunk_start) ==
  516. (h->chunk_size + 2)) {
  517. /* end of chunk reached,
  518. * new chunk starts
  519. */
  520. /* check chunk ended w/ CRLF
  521. * which we'll throw away
  522. */
  523. if (bbp[-1] == '\n' &&
  524. bbp[-2] == '\r') {
  525. } else
  526. goto bad;
  527. h->body_nbytes -= 2;
  528. bbp -= 2;
  529. h->chunk_start = h->body_nbytes;
  530. h->in_chunk_data = 0;
  531. h->chunk_size = 0; /* just in case */
  532. }
  533. } else if (h->got_content_length &&
  534. h->body_nbytes >= h->content_length) {
  535. h->got_body = 1;
  536. if (httpread_debug >= 10)
  537. wpa_printf(
  538. MSG_DEBUG,
  539. "httpread got content(%p)", h);
  540. goto got_file;
  541. }
  542. if (nread <= 0)
  543. break;
  544. /* Now transfer. Optimize using memcpy where we can. */
  545. if (h->chunked && h->in_chunk_data) {
  546. /* copy up to remainder of chunk data
  547. * plus the required CR+LF at end
  548. */
  549. ncopy = (h->chunk_start + h->chunk_size + 2) -
  550. h->body_nbytes;
  551. } else if (h->chunked) {
  552. /*in chunk header -- don't optimize */
  553. *bbp++ = *rbp++;
  554. nread--;
  555. h->body_nbytes++;
  556. continue;
  557. } else if (h->got_content_length) {
  558. ncopy = h->content_length - h->body_nbytes;
  559. } else {
  560. ncopy = nread;
  561. }
  562. /* Note: should never be 0 */
  563. if (ncopy > nread)
  564. ncopy = nread;
  565. os_memcpy(bbp, rbp, ncopy);
  566. bbp += ncopy;
  567. h->body_nbytes += ncopy;
  568. rbp += ncopy;
  569. nread -= ncopy;
  570. } /* body copy loop */
  571. } /* !got_body */
  572. if (h->chunked && h->in_trailer) {
  573. /* If "chunked" then there is always a trailer,
  574. * consisting of zero or more non-empty lines
  575. * ending with CR LF and then an empty line w/ CR LF.
  576. * We do NOT support trailers except to skip them --
  577. * this is supported (generally) by the http spec.
  578. */
  579. for (;;) {
  580. int c;
  581. if (nread <= 0)
  582. break;
  583. c = *rbp++;
  584. nread--;
  585. switch (h->trailer_state) {
  586. case trailer_line_begin:
  587. if (c == '\r')
  588. h->trailer_state = trailer_empty_cr;
  589. else
  590. h->trailer_state = trailer_nonempty;
  591. break;
  592. case trailer_empty_cr:
  593. /* end empty line */
  594. if (c == '\n') {
  595. h->trailer_state = trailer_line_begin;
  596. h->in_trailer = 0;
  597. if (httpread_debug >= 10)
  598. wpa_printf(
  599. MSG_DEBUG,
  600. "httpread got content(%p)", h);
  601. h->got_body = 1;
  602. goto got_file;
  603. }
  604. h->trailer_state = trailer_nonempty;
  605. break;
  606. case trailer_nonempty:
  607. if (c == '\r')
  608. h->trailer_state = trailer_nonempty_cr;
  609. break;
  610. case trailer_nonempty_cr:
  611. if (c == '\n')
  612. h->trailer_state = trailer_line_begin;
  613. else
  614. h->trailer_state = trailer_nonempty;
  615. break;
  616. }
  617. }
  618. }
  619. goto get_more;
  620. bad:
  621. /* Error */
  622. wpa_printf(MSG_DEBUG, "httpread read/parse failure (%p)", h);
  623. (*h->cb)(h, h->cookie, HTTPREAD_EVENT_ERROR);
  624. return;
  625. get_more:
  626. return;
  627. got_file:
  628. if (httpread_debug >= 10)
  629. wpa_printf(MSG_DEBUG,
  630. "httpread got file %d bytes type %d",
  631. h->body_nbytes, h->hdr_type);
  632. /* Null terminate for convenience of some applications */
  633. if (h->body)
  634. h->body[h->body_nbytes] = 0; /* null terminate */
  635. h->got_file = 1;
  636. /* Assume that we do NOT support keeping connection alive,
  637. * and just in case somehow we don't get destroyed right away,
  638. * unregister now.
  639. */
  640. eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
  641. /* The application can destroy us whenever they feel like...
  642. * cancel timeout.
  643. */
  644. eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
  645. (*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY);
  646. }
  647. /* httpread_create -- start a new reading session making use of eloop.
  648. * The new instance will use the socket descriptor for reading (until
  649. * it gets a file and not after) but will not close the socket, even
  650. * when the instance is destroyed (the application must do that).
  651. * Return NULL on error.
  652. *
  653. * Provided that httpread_create successfully returns a handle,
  654. * the callback fnc is called to handle httpread_event events.
  655. * The caller should do destroy on any errors or unknown events.
  656. *
  657. * Pass max_bytes == 0 to not read body at all (required for e.g.
  658. * reply to HEAD request).
  659. */
  660. struct httpread * httpread_create(
  661. int sd, /* descriptor of TCP socket to read from */
  662. void (*cb)(struct httpread *handle, void *cookie,
  663. enum httpread_event e), /* call on event */
  664. void *cookie, /* pass to callback */
  665. int max_bytes, /* maximum body size else abort it */
  666. int timeout_seconds /* 0; or total duration timeout period */
  667. )
  668. {
  669. struct httpread *h = NULL;
  670. h = os_zalloc(sizeof(*h));
  671. if (h == NULL)
  672. goto fail;
  673. h->sd = sd;
  674. h->cb = cb;
  675. h->cookie = cookie;
  676. h->max_bytes = max_bytes;
  677. h->timeout_seconds = timeout_seconds;
  678. if (timeout_seconds > 0 &&
  679. eloop_register_timeout(timeout_seconds, 0,
  680. httpread_timeout_handler, NULL, h)) {
  681. /* No way to recover (from malloc failure) */
  682. goto fail;
  683. }
  684. if (eloop_register_sock(sd, EVENT_TYPE_READ, httpread_read_handler,
  685. NULL, h)) {
  686. /* No way to recover (from malloc failure) */
  687. goto fail;
  688. }
  689. return h;
  690. fail:
  691. /* Error */
  692. httpread_destroy(h);
  693. return NULL;
  694. }
  695. /* httpread_hdr_type_get -- When file is ready, returns header type. */
  696. enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h)
  697. {
  698. return h->hdr_type;
  699. }
  700. /* httpread_uri_get -- When file is ready, uri_get returns (translated) URI
  701. * or possibly NULL (which would be an error).
  702. */
  703. char * httpread_uri_get(struct httpread *h)
  704. {
  705. return h->uri;
  706. }
  707. /* httpread_reply_code_get -- When reply is ready, returns reply code */
  708. int httpread_reply_code_get(struct httpread *h)
  709. {
  710. return h->reply_code;
  711. }
  712. /* httpread_length_get -- When file is ready, returns file length. */
  713. int httpread_length_get(struct httpread *h)
  714. {
  715. return h->body_nbytes;
  716. }
  717. /* httpread_data_get -- When file is ready, returns file content
  718. * with null byte appened.
  719. * Might return NULL in some error condition.
  720. */
  721. void * httpread_data_get(struct httpread *h)
  722. {
  723. return h->body ? h->body : "";
  724. }
  725. /* httpread_hdr_get -- When file is ready, returns header content
  726. * with null byte appended.
  727. * Might return NULL in some error condition.
  728. */
  729. char * httpread_hdr_get(struct httpread *h)
  730. {
  731. return h->hdr;
  732. }
  733. /* httpread_hdr_line_get -- When file is ready, returns pointer
  734. * to line within header content matching the given tag
  735. * (after the tag itself and any spaces/tabs).
  736. *
  737. * The tag should end with a colon for reliable matching.
  738. *
  739. * If not found, returns NULL;
  740. */
  741. char * httpread_hdr_line_get(struct httpread *h, const char *tag)
  742. {
  743. int tag_len = os_strlen(tag);
  744. char *hdr = h->hdr;
  745. hdr = os_strchr(hdr, '\n');
  746. if (hdr == NULL)
  747. return NULL;
  748. hdr++;
  749. for (;;) {
  750. if (!os_strncasecmp(hdr, tag, tag_len)) {
  751. hdr += tag_len;
  752. while (*hdr == ' ' || *hdr == '\t')
  753. hdr++;
  754. return hdr;
  755. }
  756. hdr = os_strchr(hdr, '\n');
  757. if (hdr == NULL)
  758. return NULL;
  759. hdr++;
  760. }
  761. }