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