• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #ifdef HAVE_SYS_PARAM_H
33 #include <sys/param.h>
34 #endif
35 #ifdef HAVE_SYS_TYPES_H
36 #include <sys/types.h>
37 #endif
38 
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #ifdef HAVE_SYS_IOCCOM_H
43 #include <sys/ioccom.h>
44 #endif
45 
46 #ifndef WIN32
47 #include <sys/resource.h>
48 #include <sys/socket.h>
49 #include <sys/stat.h>
50 #include <sys/wait.h>
51 #endif
52 
53 #include <sys/queue.h>
54 
55 #ifndef WIN32
56 #include <netinet/in.h>
57 #include <netdb.h>
58 #endif
59 
60 #ifdef WIN32
61 #include <winsock2.h>
62 #endif
63 
64 #include <assert.h>
65 #include <ctype.h>
66 #include <errno.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #ifndef WIN32
71 #include <syslog.h>
72 #endif
73 #include <signal.h>
74 #include <time.h>
75 #ifdef HAVE_UNISTD_H
76 #include <unistd.h>
77 #endif
78 #ifdef HAVE_FCNTL_H
79 #include <fcntl.h>
80 #endif
81 
82 #undef timeout_pending
83 #undef timeout_initialized
84 
85 #include "strlcpy-internal.h"
86 #include "event.h"
87 #include "evhttp.h"
88 #include "evutil.h"
89 #include "log.h"
90 #include "http-internal.h"
91 
92 #ifdef WIN32
93 #define strcasecmp _stricmp
94 #define strncasecmp _strnicmp
95 #define strdup _strdup
96 #endif
97 
98 #ifndef HAVE_GETNAMEINFO
99 #define NI_MAXSERV 32
100 #define NI_MAXHOST 1025
101 
102 #define NI_NUMERICHOST 1
103 #define NI_NUMERICSERV 2
104 
105 static int
fake_getnameinfo(const struct sockaddr * sa,size_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)106 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
107 	size_t hostlen, char *serv, size_t servlen, int flags)
108 {
109         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
110 
111         if (serv != NULL) {
112 				char tmpserv[16];
113 				evutil_snprintf(tmpserv, sizeof(tmpserv),
114 					"%d", ntohs(sin->sin_port));
115                 if (strlcpy(serv, tmpserv, servlen) >= servlen)
116                         return (-1);
117         }
118 
119         if (host != NULL) {
120                 if (flags & NI_NUMERICHOST) {
121                         if (strlcpy(host, inet_ntoa(sin->sin_addr),
122                             hostlen) >= hostlen)
123                                 return (-1);
124                         else
125                                 return (0);
126                 } else {
127 						struct hostent *hp;
128                         hp = gethostbyaddr((char *)&sin->sin_addr,
129                             sizeof(struct in_addr), AF_INET);
130                         if (hp == NULL)
131                                 return (-2);
132 
133                         if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
134                                 return (-1);
135                         else
136                                 return (0);
137                 }
138         }
139         return (0);
140 }
141 
142 #endif
143 
144 #ifndef HAVE_GETADDRINFO
145 struct addrinfo {
146 	int ai_family;
147 	int ai_socktype;
148 	int ai_protocol;
149 	size_t ai_addrlen;
150 	struct sockaddr *ai_addr;
151 	struct addrinfo *ai_next;
152 };
153 static int
fake_getaddrinfo(const char * hostname,struct addrinfo * ai)154 fake_getaddrinfo(const char *hostname, struct addrinfo *ai)
155 {
156 	struct hostent *he = NULL;
157 	struct sockaddr_in *sa;
158 	if (hostname) {
159 		he = gethostbyname(hostname);
160 		if (!he)
161 			return (-1);
162 	}
163 	ai->ai_family = he ? he->h_addrtype : AF_INET;
164 	ai->ai_socktype = SOCK_STREAM;
165 	ai->ai_protocol = 0;
166 	ai->ai_addrlen = sizeof(struct sockaddr_in);
167 	if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen)))
168 		return (-1);
169 	sa = (struct sockaddr_in*)ai->ai_addr;
170 	memset(sa, 0, ai->ai_addrlen);
171 	if (he) {
172 		sa->sin_family = he->h_addrtype;
173 		memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length);
174 	} else {
175 		sa->sin_family = AF_INET;
176 		sa->sin_addr.s_addr = INADDR_ANY;
177 	}
178 	ai->ai_next = NULL;
179 	return (0);
180 }
181 static void
fake_freeaddrinfo(struct addrinfo * ai)182 fake_freeaddrinfo(struct addrinfo *ai)
183 {
184 	free(ai->ai_addr);
185 }
186 #endif
187 
188 #ifndef MIN
189 #define MIN(a,b) (((a)<(b))?(a):(b))
190 #endif
191 
192 /* wrapper for setting the base from the http server */
193 #define EVHTTP_BASE_SET(x, y) do { \
194 	if ((x)->base != NULL) event_base_set((x)->base, y);	\
195 } while (0)
196 
197 extern int debug;
198 
199 static int socket_connect(int fd, const char *address, unsigned short port);
200 static int bind_socket_ai(struct addrinfo *, int reuse);
201 static int bind_socket(const char *, u_short, int reuse);
202 static void name_from_addr(struct sockaddr *, socklen_t, char **, char **);
203 static int evhttp_associate_new_request_with_connection(
204 	struct evhttp_connection *evcon);
205 static void evhttp_connection_start_detectclose(
206 	struct evhttp_connection *evcon);
207 static void evhttp_connection_stop_detectclose(
208 	struct evhttp_connection *evcon);
209 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
210 static void evhttp_read_firstline(struct evhttp_connection *evcon,
211 				  struct evhttp_request *req);
212 static void evhttp_read_header(struct evhttp_connection *evcon,
213     struct evhttp_request *req);
214 static int evhttp_add_header_internal(struct evkeyvalq *headers,
215     const char *key, const char *value);
216 static int evhttp_decode_uri_internal(const char *uri, size_t length,
217     char *ret, int always_decode_plus);
218 
219 void evhttp_read(int, short, void *);
220 void evhttp_write(int, short, void *);
221 
222 #ifndef HAVE_STRSEP
223 /* strsep replacement for platforms that lack it.  Only works if
224  * del is one character long. */
225 static char *
strsep(char ** s,const char * del)226 strsep(char **s, const char *del)
227 {
228 	char *d, *tok;
229 	assert(strlen(del) == 1);
230 	if (!s || !*s)
231 		return NULL;
232 	tok = *s;
233 	d = strstr(tok, del);
234 	if (d) {
235 		*d = '\0';
236 		*s = d + 1;
237 	} else
238 		*s = NULL;
239 	return tok;
240 }
241 #endif
242 
243 static const char *
html_replace(char ch,char * buf)244 html_replace(char ch, char *buf)
245 {
246 	switch (ch) {
247 	case '<':
248 		return "&lt;";
249 	case '>':
250 		return "&gt;";
251 	case '"':
252 		return "&quot;";
253 	case '\'':
254 		return "&#039;";
255 	case '&':
256 		return "&amp;";
257 	default:
258 		break;
259 	}
260 
261 	/* Echo the character back */
262 	buf[0] = ch;
263 	buf[1] = '\0';
264 
265 	return buf;
266 }
267 
268 /*
269  * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
270  * &#039; and &amp; correspondingly.
271  *
272  * The returned string needs to be freed by the caller.
273  */
274 
275 char *
evhttp_htmlescape(const char * html)276 evhttp_htmlescape(const char *html)
277 {
278 	int i, new_size = 0, old_size = strlen(html);
279 	char *escaped_html, *p;
280 	char scratch_space[2];
281 
282 	for (i = 0; i < old_size; ++i)
283           new_size += strlen(html_replace(html[i], scratch_space));
284 
285 	p = escaped_html = malloc(new_size + 1);
286 	if (escaped_html == NULL)
287 		event_err(1, "%s: malloc(%d)", __func__, new_size + 1);
288 	for (i = 0; i < old_size; ++i) {
289 		const char *replaced = html_replace(html[i], scratch_space);
290 		/* this is length checked */
291 		strcpy(p, replaced);
292 		p += strlen(replaced);
293 	}
294 
295 	*p = '\0';
296 
297 	return (escaped_html);
298 }
299 
300 static const char *
evhttp_method(enum evhttp_cmd_type type)301 evhttp_method(enum evhttp_cmd_type type)
302 {
303 	const char *method;
304 
305 	switch (type) {
306 	case EVHTTP_REQ_GET:
307 		method = "GET";
308 		break;
309 	case EVHTTP_REQ_POST:
310 		method = "POST";
311 		break;
312 	case EVHTTP_REQ_HEAD:
313 		method = "HEAD";
314 		break;
315 	default:
316 		method = NULL;
317 		break;
318 	}
319 
320 	return (method);
321 }
322 
323 static void
evhttp_add_event(struct event * ev,int timeout,int default_timeout)324 evhttp_add_event(struct event *ev, int timeout, int default_timeout)
325 {
326 	if (timeout != 0) {
327 		struct timeval tv;
328 
329 		evutil_timerclear(&tv);
330 		tv.tv_sec = timeout != -1 ? timeout : default_timeout;
331 		event_add(ev, &tv);
332 	} else {
333 		event_add(ev, NULL);
334 	}
335 }
336 
337 void
evhttp_write_buffer(struct evhttp_connection * evcon,void (* cb)(struct evhttp_connection *,void *),void * arg)338 evhttp_write_buffer(struct evhttp_connection *evcon,
339     void (*cb)(struct evhttp_connection *, void *), void *arg)
340 {
341 	event_debug(("%s: preparing to write buffer\n", __func__));
342 
343 	/* Set call back */
344 	evcon->cb = cb;
345 	evcon->cb_arg = arg;
346 
347 	/* check if the event is already pending */
348 	if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL))
349 		event_del(&evcon->ev);
350 
351 	event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon);
352 	EVHTTP_BASE_SET(evcon, &evcon->ev);
353 	evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT);
354 }
355 
356 static int
evhttp_connected(struct evhttp_connection * evcon)357 evhttp_connected(struct evhttp_connection *evcon)
358 {
359 	switch (evcon->state) {
360 	case EVCON_DISCONNECTED:
361 	case EVCON_CONNECTING:
362 		return (0);
363 	case EVCON_IDLE:
364 	case EVCON_READING_FIRSTLINE:
365 	case EVCON_READING_HEADERS:
366 	case EVCON_READING_BODY:
367 	case EVCON_READING_TRAILER:
368 	case EVCON_WRITING:
369 	default:
370 		return (1);
371 	}
372 }
373 
374 /*
375  * Create the headers needed for an HTTP request
376  */
377 static void
evhttp_make_header_request(struct evhttp_connection * evcon,struct evhttp_request * req)378 evhttp_make_header_request(struct evhttp_connection *evcon,
379     struct evhttp_request *req)
380 {
381 	const char *method;
382 
383 	evhttp_remove_header(req->output_headers, "Proxy-Connection");
384 
385 	/* Generate request line */
386 	method = evhttp_method(req->type);
387 	evbuffer_add_printf(evcon->output_buffer, "%s %s HTTP/%d.%d\r\n",
388 	    method, req->uri, req->major, req->minor);
389 
390 	/* Add the content length on a post request if missing */
391 	if (req->type == EVHTTP_REQ_POST &&
392 	    evhttp_find_header(req->output_headers, "Content-Length") == NULL){
393 		char size[12];
394 		evutil_snprintf(size, sizeof(size), "%ld",
395 		    (long)EVBUFFER_LENGTH(req->output_buffer));
396 		evhttp_add_header(req->output_headers, "Content-Length", size);
397 	}
398 }
399 
400 static int
evhttp_is_connection_close(int flags,struct evkeyvalq * headers)401 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
402 {
403 	if (flags & EVHTTP_PROXY_REQUEST) {
404 		/* proxy connection */
405 		const char *connection = evhttp_find_header(headers, "Proxy-Connection");
406 		return (connection == NULL || strcasecmp(connection, "keep-alive") != 0);
407 	} else {
408 		const char *connection = evhttp_find_header(headers, "Connection");
409 		return (connection != NULL && strcasecmp(connection, "close") == 0);
410 	}
411 }
412 
413 static int
evhttp_is_connection_keepalive(struct evkeyvalq * headers)414 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
415 {
416 	const char *connection = evhttp_find_header(headers, "Connection");
417 	return (connection != NULL
418 	    && strncasecmp(connection, "keep-alive", 10) == 0);
419 }
420 
421 static void
evhttp_maybe_add_date_header(struct evkeyvalq * headers)422 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
423 {
424 	if (evhttp_find_header(headers, "Date") == NULL) {
425 		char date[50];
426 #ifndef WIN32
427 		struct tm cur;
428 #endif
429 		struct tm *cur_p;
430 		time_t t = time(NULL);
431 #ifdef WIN32
432 		cur_p = gmtime(&t);
433 #else
434 		gmtime_r(&t, &cur);
435 		cur_p = &cur;
436 #endif
437 		if (strftime(date, sizeof(date),
438 			"%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
439 			evhttp_add_header(headers, "Date", date);
440 		}
441 	}
442 }
443 
444 static void
evhttp_maybe_add_content_length_header(struct evkeyvalq * headers,long content_length)445 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
446     long content_length)
447 {
448 	if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
449 	    evhttp_find_header(headers,	"Content-Length") == NULL) {
450 		char len[12];
451 		evutil_snprintf(len, sizeof(len), "%ld", content_length);
452 		evhttp_add_header(headers, "Content-Length", len);
453 	}
454 }
455 
456 /*
457  * Create the headers needed for an HTTP reply
458  */
459 
460 static void
evhttp_make_header_response(struct evhttp_connection * evcon,struct evhttp_request * req)461 evhttp_make_header_response(struct evhttp_connection *evcon,
462     struct evhttp_request *req)
463 {
464 	int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
465 	evbuffer_add_printf(evcon->output_buffer, "HTTP/%d.%d %d %s\r\n",
466 	    req->major, req->minor, req->response_code,
467 	    req->response_code_line);
468 
469 	if (req->major == 1) {
470 		if (req->minor == 1)
471 			evhttp_maybe_add_date_header(req->output_headers);
472 
473 		/*
474 		 * if the protocol is 1.0; and the connection was keep-alive
475 		 * we need to add a keep-alive header, too.
476 		 */
477 		if (req->minor == 0 && is_keepalive)
478 			evhttp_add_header(req->output_headers,
479 			    "Connection", "keep-alive");
480 
481 		if (req->minor == 1 || is_keepalive) {
482 			/*
483 			 * we need to add the content length if the
484 			 * user did not give it, this is required for
485 			 * persistent connections to work.
486 			 */
487 			evhttp_maybe_add_content_length_header(
488 				req->output_headers,
489 				(long)EVBUFFER_LENGTH(req->output_buffer));
490 		}
491 	}
492 
493 	/* Potentially add headers for unidentified content. */
494 	if (EVBUFFER_LENGTH(req->output_buffer)) {
495 		if (evhttp_find_header(req->output_headers,
496 			"Content-Type") == NULL) {
497 			evhttp_add_header(req->output_headers,
498 			    "Content-Type", "text/html; charset=ISO-8859-1");
499 		}
500 	}
501 
502 	/* if the request asked for a close, we send a close, too */
503 	if (evhttp_is_connection_close(req->flags, req->input_headers)) {
504 		evhttp_remove_header(req->output_headers, "Connection");
505 		if (!(req->flags & EVHTTP_PROXY_REQUEST))
506 		    evhttp_add_header(req->output_headers, "Connection", "close");
507 		evhttp_remove_header(req->output_headers, "Proxy-Connection");
508 	}
509 }
510 
511 void
evhttp_make_header(struct evhttp_connection * evcon,struct evhttp_request * req)512 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
513 {
514 	struct evkeyval *header;
515 
516 	/*
517 	 * Depending if this is a HTTP request or response, we might need to
518 	 * add some new headers or remove existing headers.
519 	 */
520 	if (req->kind == EVHTTP_REQUEST) {
521 		evhttp_make_header_request(evcon, req);
522 	} else {
523 		evhttp_make_header_response(evcon, req);
524 	}
525 
526 	TAILQ_FOREACH(header, req->output_headers, next) {
527 		evbuffer_add_printf(evcon->output_buffer, "%s: %s\r\n",
528 		    header->key, header->value);
529 	}
530 	evbuffer_add(evcon->output_buffer, "\r\n", 2);
531 
532 	if (EVBUFFER_LENGTH(req->output_buffer) > 0) {
533 		/*
534 		 * For a request, we add the POST data, for a reply, this
535 		 * is the regular data.
536 		 */
537 		evbuffer_add_buffer(evcon->output_buffer, req->output_buffer);
538 	}
539 }
540 
541 /* Separated host, port and file from URI */
542 
543 int
evhttp_hostportfile(char * url,char ** phost,u_short * pport,char ** pfile)544 evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile)
545 {
546 	/* XXX not threadsafe. */
547 	static char host[1024];
548 	static char file[1024];
549 	char *p;
550 	const char *p2;
551 	int len;
552 	u_short port;
553 
554 	len = strlen(HTTP_PREFIX);
555 	if (strncasecmp(url, HTTP_PREFIX, len))
556 		return (-1);
557 
558 	url += len;
559 
560 	/* We might overrun */
561 	if (strlcpy(host, url, sizeof (host)) >= sizeof(host))
562 		return (-1);
563 
564 	p = strchr(host, '/');
565 	if (p != NULL) {
566 		*p = '\0';
567 		p2 = p + 1;
568 	} else
569 		p2 = NULL;
570 
571 	if (pfile != NULL) {
572 		/* Generate request file */
573 		if (p2 == NULL)
574 			p2 = "";
575 		evutil_snprintf(file, sizeof(file), "/%s", p2);
576 	}
577 
578 	p = strchr(host, ':');
579 	if (p != NULL) {
580 		*p = '\0';
581 		port = atoi(p + 1);
582 
583 		if (port == 0)
584 			return (-1);
585 	} else
586 		port = HTTP_DEFAULTPORT;
587 
588 	if (phost != NULL)
589 		*phost = host;
590 	if (pport != NULL)
591 		*pport = port;
592 	if (pfile != NULL)
593 		*pfile = file;
594 
595 	return (0);
596 }
597 
598 static int
evhttp_connection_incoming_fail(struct evhttp_request * req,enum evhttp_connection_error error)599 evhttp_connection_incoming_fail(struct evhttp_request *req,
600     enum evhttp_connection_error error)
601 {
602 	switch (error) {
603 	case EVCON_HTTP_TIMEOUT:
604 	case EVCON_HTTP_EOF:
605 		/*
606 		 * these are cases in which we probably should just
607 		 * close the connection and not send a reply.  this
608 		 * case may happen when a browser keeps a persistent
609 		 * connection open and we timeout on the read.
610 		 */
611 		return (-1);
612 	case EVCON_HTTP_INVALID_HEADER:
613 	default:	/* xxx: probably should just error on default */
614 		/* the callback looks at the uri to determine errors */
615 		if (req->uri) {
616 			free(req->uri);
617 			req->uri = NULL;
618 		}
619 
620 		/*
621 		 * the callback needs to send a reply, once the reply has
622 		 * been send, the connection should get freed.
623 		 */
624 		(*req->cb)(req, req->cb_arg);
625 	}
626 
627 	return (0);
628 }
629 
630 void
evhttp_connection_fail(struct evhttp_connection * evcon,enum evhttp_connection_error error)631 evhttp_connection_fail(struct evhttp_connection *evcon,
632     enum evhttp_connection_error error)
633 {
634 	struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
635 	void (*cb)(struct evhttp_request *, void *);
636 	void *cb_arg;
637 	assert(req != NULL);
638 
639 	if (evcon->flags & EVHTTP_CON_INCOMING) {
640 		/*
641 		 * for incoming requests, there are two different
642 		 * failure cases.  it's either a network level error
643 		 * or an http layer error. for problems on the network
644 		 * layer like timeouts we just drop the connections.
645 		 * For HTTP problems, we might have to send back a
646 		 * reply before the connection can be freed.
647 		 */
648 		if (evhttp_connection_incoming_fail(req, error) == -1)
649 			evhttp_connection_free(evcon);
650 		return;
651 	}
652 
653 	/* save the callback for later; the cb might free our object */
654 	cb = req->cb;
655 	cb_arg = req->cb_arg;
656 
657 	TAILQ_REMOVE(&evcon->requests, req, next);
658 	evhttp_request_free(req);
659 
660 	/* xxx: maybe we should fail all requests??? */
661 
662 	/* reset the connection */
663 	evhttp_connection_reset(evcon);
664 
665 	/* We are trying the next request that was queued on us */
666 	if (TAILQ_FIRST(&evcon->requests) != NULL)
667 		evhttp_connection_connect(evcon);
668 
669 	/* inform the user */
670 	if (cb != NULL)
671 		(*cb)(NULL, cb_arg);
672 }
673 
674 void
evhttp_write(int fd,short what,void * arg)675 evhttp_write(int fd, short what, void *arg)
676 {
677 	struct evhttp_connection *evcon = arg;
678 	int n;
679 
680 	if (what == EV_TIMEOUT) {
681 		evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
682 		return;
683 	}
684 
685 	n = evbuffer_write(evcon->output_buffer, fd);
686 	if (n == -1) {
687 		event_debug(("%s: evbuffer_write", __func__));
688 		evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
689 		return;
690 	}
691 
692 	if (n == 0) {
693 		event_debug(("%s: write nothing", __func__));
694 		evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
695 		return;
696 	}
697 
698 	if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
699 		evhttp_add_event(&evcon->ev,
700 		    evcon->timeout, HTTP_WRITE_TIMEOUT);
701 		return;
702 	}
703 
704 	/* Activate our call back */
705 	if (evcon->cb != NULL)
706 		(*evcon->cb)(evcon, evcon->cb_arg);
707 }
708 
709 /**
710  * Advance the connection state.
711  * - If this is an outgoing connection, we've just processed the response;
712  *   idle or close the connection.
713  * - If this is an incoming connection, we've just processed the request;
714  *   respond.
715  */
716 static void
evhttp_connection_done(struct evhttp_connection * evcon)717 evhttp_connection_done(struct evhttp_connection *evcon)
718 {
719 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
720 	int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
721 
722 	if (con_outgoing) {
723 		/* idle or close the connection */
724 	        int need_close;
725 		TAILQ_REMOVE(&evcon->requests, req, next);
726 		req->evcon = NULL;
727 
728 		evcon->state = EVCON_IDLE;
729 
730 		need_close =
731 		    evhttp_is_connection_close(req->flags, req->input_headers)||
732 		    evhttp_is_connection_close(req->flags, req->output_headers);
733 
734 		/* check if we got asked to close the connection */
735 		if (need_close)
736 			evhttp_connection_reset(evcon);
737 
738 		if (TAILQ_FIRST(&evcon->requests) != NULL) {
739 			/*
740 			 * We have more requests; reset the connection
741 			 * and deal with the next request.
742 			 */
743 			if (!evhttp_connected(evcon))
744 				evhttp_connection_connect(evcon);
745 			else
746 				evhttp_request_dispatch(evcon);
747 		} else if (!need_close) {
748 			/*
749 			 * The connection is going to be persistent, but we
750 			 * need to detect if the other side closes it.
751 			 */
752 			evhttp_connection_start_detectclose(evcon);
753 		}
754 	} else {
755 		/*
756 		 * incoming connection - we need to leave the request on the
757 		 * connection so that we can reply to it.
758 		 */
759 		evcon->state = EVCON_WRITING;
760 	}
761 
762 	/* notify the user of the request */
763 	(*req->cb)(req, req->cb_arg);
764 
765 	/* if this was an outgoing request, we own and it's done. so free it */
766 	if (con_outgoing) {
767 		evhttp_request_free(req);
768 	}
769 }
770 
771 /*
772  * Handles reading from a chunked request.
773  *   return ALL_DATA_READ:
774  *     all data has been read
775  *   return MORE_DATA_EXPECTED:
776  *     more data is expected
777  *   return DATA_CORRUPTED:
778  *     data is corrupted
779  *   return REQUEST_CANCLED:
780  *     request was canceled by the user calling evhttp_cancel_request
781  */
782 
783 static enum message_read_status
evhttp_handle_chunked_read(struct evhttp_request * req,struct evbuffer * buf)784 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
785 {
786 	int len;
787 
788 	while ((len = EVBUFFER_LENGTH(buf)) > 0) {
789 		if (req->ntoread < 0) {
790 			/* Read chunk size */
791 			ev_int64_t ntoread;
792 			char *p = evbuffer_readline(buf);
793 			char *endp;
794 			int error;
795 			if (p == NULL)
796 				break;
797 			/* the last chunk is on a new line? */
798 			if (strlen(p) == 0) {
799 				free(p);
800 				continue;
801 			}
802 			ntoread = evutil_strtoll(p, &endp, 16);
803 			error = (*p == '\0' ||
804 			    (*endp != '\0' && *endp != ' ') ||
805 			    ntoread < 0);
806 			free(p);
807 			if (error) {
808 				/* could not get chunk size */
809 				return (DATA_CORRUPTED);
810 			}
811 			req->ntoread = ntoread;
812 			if (req->ntoread == 0) {
813 				/* Last chunk */
814 				return (ALL_DATA_READ);
815 			}
816 			continue;
817 		}
818 
819 		/* don't have enough to complete a chunk; wait for more */
820 		if (len < req->ntoread)
821 			return (MORE_DATA_EXPECTED);
822 
823 		/* Completed chunk */
824 		evbuffer_add(req->input_buffer,
825 		    EVBUFFER_DATA(buf), (size_t)req->ntoread);
826 		evbuffer_drain(buf, (size_t)req->ntoread);
827 		req->ntoread = -1;
828 		if (req->chunk_cb != NULL) {
829 			(*req->chunk_cb)(req, req->cb_arg);
830 			evbuffer_drain(req->input_buffer,
831 			    EVBUFFER_LENGTH(req->input_buffer));
832 		}
833 	}
834 
835 	return (MORE_DATA_EXPECTED);
836 }
837 
838 static void
evhttp_read_trailer(struct evhttp_connection * evcon,struct evhttp_request * req)839 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
840 {
841 	struct evbuffer *buf = evcon->input_buffer;
842 
843 	switch (evhttp_parse_headers(req, buf)) {
844 	case DATA_CORRUPTED:
845 		evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
846 		break;
847 	case ALL_DATA_READ:
848 		event_del(&evcon->ev);
849 		evhttp_connection_done(evcon);
850 		break;
851 	case MORE_DATA_EXPECTED:
852 	default:
853 		evhttp_add_event(&evcon->ev, evcon->timeout,
854 		    HTTP_READ_TIMEOUT);
855 		break;
856 	}
857 }
858 
859 static void
evhttp_read_body(struct evhttp_connection * evcon,struct evhttp_request * req)860 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
861 {
862 	struct evbuffer *buf = evcon->input_buffer;
863 
864 	if (req->chunked) {
865 		switch (evhttp_handle_chunked_read(req, buf)) {
866 		case ALL_DATA_READ:
867 			/* finished last chunk */
868 			evcon->state = EVCON_READING_TRAILER;
869 			evhttp_read_trailer(evcon, req);
870 			return;
871 		case DATA_CORRUPTED:
872 			/* corrupted data */
873 			evhttp_connection_fail(evcon,
874 			    EVCON_HTTP_INVALID_HEADER);
875 			return;
876 		case REQUEST_CANCELED:
877 			/* request canceled */
878 			evhttp_request_free(req);
879 			return;
880 		case MORE_DATA_EXPECTED:
881 		default:
882 			break;
883 		}
884 	} else if (req->ntoread < 0) {
885 		/* Read until connection close. */
886 		evbuffer_add_buffer(req->input_buffer, buf);
887 	} else if (EVBUFFER_LENGTH(buf) >= req->ntoread) {
888 		/* Completed content length */
889 		evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf),
890 		    (size_t)req->ntoread);
891 		evbuffer_drain(buf, (size_t)req->ntoread);
892 		req->ntoread = 0;
893 		evhttp_connection_done(evcon);
894 		return;
895 	}
896 	/* Read more! */
897 	event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
898 	EVHTTP_BASE_SET(evcon, &evcon->ev);
899 	evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
900 }
901 
902 /*
903  * Reads data into a buffer structure until no more data
904  * can be read on the file descriptor or we have read all
905  * the data that we wanted to read.
906  * Execute callback when done.
907  */
908 
909 void
evhttp_read(int fd,short what,void * arg)910 evhttp_read(int fd, short what, void *arg)
911 {
912 	struct evhttp_connection *evcon = arg;
913 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
914 	struct evbuffer *buf = evcon->input_buffer;
915 	int n, len;
916 
917 	if (what == EV_TIMEOUT) {
918 		evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
919 		return;
920 	}
921 	n = evbuffer_read(buf, fd, -1);
922 	len = EVBUFFER_LENGTH(buf);
923 	event_debug(("%s: got %d on %d\n", __func__, n, fd));
924 
925 	if (n == -1) {
926 		if (errno != EINTR && errno != EAGAIN) {
927 			event_debug(("%s: evbuffer_read", __func__));
928 			evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
929 		} else {
930 			evhttp_add_event(&evcon->ev, evcon->timeout,
931 			    HTTP_READ_TIMEOUT);
932 		}
933 		return;
934 	} else if (n == 0) {
935 		/* Connection closed */
936 		evhttp_connection_done(evcon);
937 		return;
938 	}
939 
940 	switch (evcon->state) {
941 	case EVCON_READING_FIRSTLINE:
942 		evhttp_read_firstline(evcon, req);
943 		break;
944 	case EVCON_READING_HEADERS:
945 		evhttp_read_header(evcon, req);
946 		break;
947 	case EVCON_READING_BODY:
948 		evhttp_read_body(evcon, req);
949 		break;
950 	case EVCON_READING_TRAILER:
951 		evhttp_read_trailer(evcon, req);
952 		break;
953 	case EVCON_DISCONNECTED:
954 	case EVCON_CONNECTING:
955 	case EVCON_IDLE:
956 	case EVCON_WRITING:
957 	default:
958 		event_errx(1, "%s: illegal connection state %d",
959 			   __func__, evcon->state);
960 	}
961 }
962 
963 static void
evhttp_write_connectioncb(struct evhttp_connection * evcon,void * arg)964 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
965 {
966 	/* This is after writing the request to the server */
967 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
968 	assert(req != NULL);
969 
970 	assert(evcon->state == EVCON_WRITING);
971 
972 	/* We are done writing our header and are now expecting the response */
973 	req->kind = EVHTTP_RESPONSE;
974 
975 	evhttp_start_read(evcon);
976 }
977 
978 /*
979  * Clean up a connection object
980  */
981 
982 void
evhttp_connection_free(struct evhttp_connection * evcon)983 evhttp_connection_free(struct evhttp_connection *evcon)
984 {
985 	struct evhttp_request *req;
986 
987 	/* notify interested parties that this connection is going down */
988 	if (evcon->fd != -1) {
989 		if (evhttp_connected(evcon) && evcon->closecb != NULL)
990 			(*evcon->closecb)(evcon, evcon->closecb_arg);
991 	}
992 
993 	/* remove all requests that might be queued on this connection */
994 	while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
995 		TAILQ_REMOVE(&evcon->requests, req, next);
996 		evhttp_request_free(req);
997 	}
998 
999 	if (evcon->http_server != NULL) {
1000 		struct evhttp *http = evcon->http_server;
1001 		TAILQ_REMOVE(&http->connections, evcon, next);
1002 	}
1003 
1004 	if (event_initialized(&evcon->close_ev))
1005 		event_del(&evcon->close_ev);
1006 
1007 	if (event_initialized(&evcon->ev))
1008 		event_del(&evcon->ev);
1009 
1010 	if (evcon->fd != -1)
1011 		EVUTIL_CLOSESOCKET(evcon->fd);
1012 
1013 	if (evcon->bind_address != NULL)
1014 		free(evcon->bind_address);
1015 
1016 	if (evcon->address != NULL)
1017 		free(evcon->address);
1018 
1019 	if (evcon->input_buffer != NULL)
1020 		evbuffer_free(evcon->input_buffer);
1021 
1022 	if (evcon->output_buffer != NULL)
1023 		evbuffer_free(evcon->output_buffer);
1024 
1025 	free(evcon);
1026 }
1027 
1028 void
evhttp_connection_set_local_address(struct evhttp_connection * evcon,const char * address)1029 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1030     const char *address)
1031 {
1032 	assert(evcon->state == EVCON_DISCONNECTED);
1033 	if (evcon->bind_address)
1034 		free(evcon->bind_address);
1035 	if ((evcon->bind_address = strdup(address)) == NULL)
1036 		event_err(1, "%s: strdup", __func__);
1037 }
1038 
1039 void
evhttp_connection_set_local_port(struct evhttp_connection * evcon,unsigned short port)1040 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1041     unsigned short port)
1042 {
1043 	assert(evcon->state == EVCON_DISCONNECTED);
1044 	evcon->bind_port = port;
1045 }
1046 
1047 static void
evhttp_request_dispatch(struct evhttp_connection * evcon)1048 evhttp_request_dispatch(struct evhttp_connection* evcon)
1049 {
1050 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1051 
1052 	/* this should not usually happy but it's possible */
1053 	if (req == NULL)
1054 		return;
1055 
1056 	/* delete possible close detection events */
1057 	evhttp_connection_stop_detectclose(evcon);
1058 
1059 	/* we assume that the connection is connected already */
1060 	assert(evcon->state == EVCON_IDLE);
1061 
1062 	evcon->state = EVCON_WRITING;
1063 
1064 	/* Create the header from the store arguments */
1065 	evhttp_make_header(evcon, req);
1066 
1067 	evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1068 }
1069 
1070 /* Reset our connection state */
1071 void
evhttp_connection_reset(struct evhttp_connection * evcon)1072 evhttp_connection_reset(struct evhttp_connection *evcon)
1073 {
1074 	if (event_initialized(&evcon->ev))
1075 		event_del(&evcon->ev);
1076 
1077 	if (evcon->fd != -1) {
1078 		/* inform interested parties about connection close */
1079 		if (evhttp_connected(evcon) && evcon->closecb != NULL)
1080 			(*evcon->closecb)(evcon, evcon->closecb_arg);
1081 
1082 		EVUTIL_CLOSESOCKET(evcon->fd);
1083 		evcon->fd = -1;
1084 	}
1085 	evcon->state = EVCON_DISCONNECTED;
1086 
1087 	evbuffer_drain(evcon->input_buffer,
1088 	    EVBUFFER_LENGTH(evcon->input_buffer));
1089 	evbuffer_drain(evcon->output_buffer,
1090 	    EVBUFFER_LENGTH(evcon->output_buffer));
1091 }
1092 
1093 static void
evhttp_detect_close_cb(int fd,short what,void * arg)1094 evhttp_detect_close_cb(int fd, short what, void *arg)
1095 {
1096 	struct evhttp_connection *evcon = arg;
1097 	evhttp_connection_reset(evcon);
1098 }
1099 
1100 static void
evhttp_connection_start_detectclose(struct evhttp_connection * evcon)1101 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1102 {
1103 	evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1104 
1105 	if (event_initialized(&evcon->close_ev))
1106 		event_del(&evcon->close_ev);
1107 	event_set(&evcon->close_ev, evcon->fd, EV_READ,
1108 	    evhttp_detect_close_cb, evcon);
1109 	EVHTTP_BASE_SET(evcon, &evcon->close_ev);
1110 	event_add(&evcon->close_ev, NULL);
1111 }
1112 
1113 static void
evhttp_connection_stop_detectclose(struct evhttp_connection * evcon)1114 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1115 {
1116 	evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1117 	event_del(&evcon->close_ev);
1118 }
1119 
1120 static void
evhttp_connection_retry(int fd,short what,void * arg)1121 evhttp_connection_retry(int fd, short what, void *arg)
1122 {
1123 	struct evhttp_connection *evcon = arg;
1124 
1125 	evcon->state = EVCON_DISCONNECTED;
1126 	evhttp_connection_connect(evcon);
1127 }
1128 
1129 /*
1130  * Call back for asynchronous connection attempt.
1131  */
1132 
1133 static void
evhttp_connectioncb(int fd,short what,void * arg)1134 evhttp_connectioncb(int fd, short what, void *arg)
1135 {
1136 	struct evhttp_connection *evcon = arg;
1137 	int error;
1138 	socklen_t errsz = sizeof(error);
1139 
1140 	if (what == EV_TIMEOUT) {
1141 		event_debug(("%s: connection timeout for \"%s:%d\" on %d",
1142 			__func__, evcon->address, evcon->port, evcon->fd));
1143 		goto cleanup;
1144 	}
1145 
1146 	/* Check if the connection completed */
1147 	if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1148 		       &errsz) == -1) {
1149 		event_debug(("%s: getsockopt for \"%s:%d\" on %d",
1150 			__func__, evcon->address, evcon->port, evcon->fd));
1151 		goto cleanup;
1152 	}
1153 
1154 	if (error) {
1155 		event_debug(("%s: connect failed for \"%s:%d\" on %d: %s",
1156 		    __func__, evcon->address, evcon->port, evcon->fd,
1157 			strerror(error)));
1158 		goto cleanup;
1159 	}
1160 
1161 	/* We are connected to the server now */
1162 	event_debug(("%s: connected to \"%s:%d\" on %d\n",
1163 			__func__, evcon->address, evcon->port, evcon->fd));
1164 
1165 	/* Reset the retry count as we were successful in connecting */
1166 	evcon->retry_cnt = 0;
1167 	evcon->state = EVCON_IDLE;
1168 
1169 	/* try to start requests that have queued up on this connection */
1170 	evhttp_request_dispatch(evcon);
1171 	return;
1172 
1173  cleanup:
1174 	if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1175 		evtimer_set(&evcon->ev, evhttp_connection_retry, evcon);
1176 		EVHTTP_BASE_SET(evcon, &evcon->ev);
1177 		evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt),
1178 		    HTTP_CONNECT_TIMEOUT);
1179 		evcon->retry_cnt++;
1180 		return;
1181 	}
1182 	evhttp_connection_reset(evcon);
1183 
1184 	/* for now, we just signal all requests by executing their callbacks */
1185 	while (TAILQ_FIRST(&evcon->requests) != NULL) {
1186 		struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1187 		TAILQ_REMOVE(&evcon->requests, request, next);
1188 		request->evcon = NULL;
1189 
1190 		/* we might want to set an error here */
1191 		request->cb(request, request->cb_arg);
1192 		evhttp_request_free(request);
1193 	}
1194 }
1195 
1196 /*
1197  * Check if we got a valid response code.
1198  */
1199 
1200 static int
evhttp_valid_response_code(int code)1201 evhttp_valid_response_code(int code)
1202 {
1203 	if (code == 0)
1204 		return (0);
1205 
1206 	return (1);
1207 }
1208 
1209 /* Parses the status line of a web server */
1210 
1211 static int
evhttp_parse_response_line(struct evhttp_request * req,char * line)1212 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1213 {
1214 	char *protocol;
1215 	char *number;
1216 	char *readable;
1217 
1218 	protocol = strsep(&line, " ");
1219 	if (line == NULL)
1220 		return (-1);
1221 	number = strsep(&line, " ");
1222 	if (line == NULL)
1223 		return (-1);
1224 	readable = line;
1225 
1226 	if (strcmp(protocol, "HTTP/1.0") == 0) {
1227 		req->major = 1;
1228 		req->minor = 0;
1229 	} else if (strcmp(protocol, "HTTP/1.1") == 0) {
1230 		req->major = 1;
1231 		req->minor = 1;
1232 	} else {
1233 		event_debug(("%s: bad protocol \"%s\"",
1234 			__func__, protocol));
1235 		return (-1);
1236 	}
1237 
1238 	req->response_code = atoi(number);
1239 	if (!evhttp_valid_response_code(req->response_code)) {
1240 		event_debug(("%s: bad response code \"%s\"",
1241 			__func__, number));
1242 		return (-1);
1243 	}
1244 
1245 	if ((req->response_code_line = strdup(readable)) == NULL)
1246 		event_err(1, "%s: strdup", __func__);
1247 
1248 	return (0);
1249 }
1250 
1251 /* Parse the first line of a HTTP request */
1252 
1253 static int
evhttp_parse_request_line(struct evhttp_request * req,char * line)1254 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1255 {
1256 	char *method;
1257 	char *uri;
1258 	char *version;
1259 
1260 	/* Parse the request line */
1261 	method = strsep(&line, " ");
1262 	if (line == NULL)
1263 		return (-1);
1264 	uri = strsep(&line, " ");
1265 	if (line == NULL)
1266 		return (-1);
1267 	version = strsep(&line, " ");
1268 	if (line != NULL)
1269 		return (-1);
1270 
1271 	/* First line */
1272 	if (strcmp(method, "GET") == 0) {
1273 		req->type = EVHTTP_REQ_GET;
1274 	} else if (strcmp(method, "POST") == 0) {
1275 		req->type = EVHTTP_REQ_POST;
1276 	} else if (strcmp(method, "HEAD") == 0) {
1277 		req->type = EVHTTP_REQ_HEAD;
1278 	} else {
1279 		event_debug(("%s: bad method %s on request %p from %s",
1280 			__func__, method, req, req->remote_host));
1281 		return (-1);
1282 	}
1283 
1284 	if (strcmp(version, "HTTP/1.0") == 0) {
1285 		req->major = 1;
1286 		req->minor = 0;
1287 	} else if (strcmp(version, "HTTP/1.1") == 0) {
1288 		req->major = 1;
1289 		req->minor = 1;
1290 	} else {
1291 		event_debug(("%s: bad version %s on request %p from %s",
1292 			__func__, version, req, req->remote_host));
1293 		return (-1);
1294 	}
1295 
1296 	if ((req->uri = strdup(uri)) == NULL) {
1297 		event_debug(("%s: evhttp_decode_uri", __func__));
1298 		return (-1);
1299 	}
1300 
1301 	/* determine if it's a proxy request */
1302 	if (strlen(req->uri) > 0 && req->uri[0] != '/')
1303 		req->flags |= EVHTTP_PROXY_REQUEST;
1304 
1305 	return (0);
1306 }
1307 
1308 const char *
evhttp_find_header(const struct evkeyvalq * headers,const char * key)1309 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1310 {
1311 	struct evkeyval *header;
1312 
1313 	TAILQ_FOREACH(header, headers, next) {
1314 		if (strcasecmp(header->key, key) == 0)
1315 			return (header->value);
1316 	}
1317 
1318 	return (NULL);
1319 }
1320 
1321 void
evhttp_clear_headers(struct evkeyvalq * headers)1322 evhttp_clear_headers(struct evkeyvalq *headers)
1323 {
1324 	struct evkeyval *header;
1325 
1326 	for (header = TAILQ_FIRST(headers);
1327 	    header != NULL;
1328 	    header = TAILQ_FIRST(headers)) {
1329 		TAILQ_REMOVE(headers, header, next);
1330 		free(header->key);
1331 		free(header->value);
1332 		free(header);
1333 	}
1334 }
1335 
1336 /*
1337  * Returns 0,  if the header was successfully removed.
1338  * Returns -1, if the header could not be found.
1339  */
1340 
1341 int
evhttp_remove_header(struct evkeyvalq * headers,const char * key)1342 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1343 {
1344 	struct evkeyval *header;
1345 
1346 	TAILQ_FOREACH(header, headers, next) {
1347 		if (strcasecmp(header->key, key) == 0)
1348 			break;
1349 	}
1350 
1351 	if (header == NULL)
1352 		return (-1);
1353 
1354 	/* Free and remove the header that we found */
1355 	TAILQ_REMOVE(headers, header, next);
1356 	free(header->key);
1357 	free(header->value);
1358 	free(header);
1359 
1360 	return (0);
1361 }
1362 
1363 static int
evhttp_header_is_valid_value(const char * value)1364 evhttp_header_is_valid_value(const char *value)
1365 {
1366 	const char *p = value;
1367 
1368 	while ((p = strpbrk(p, "\r\n")) != NULL) {
1369 		/* we really expect only one new line */
1370 		p += strspn(p, "\r\n");
1371 		/* we expect a space or tab for continuation */
1372 		if (*p != ' ' && *p != '\t')
1373 			return (0);
1374 	}
1375 	return (1);
1376 }
1377 
1378 int
evhttp_add_header(struct evkeyvalq * headers,const char * key,const char * value)1379 evhttp_add_header(struct evkeyvalq *headers,
1380     const char *key, const char *value)
1381 {
1382 	event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1383 
1384 	if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1385 		/* drop illegal headers */
1386 		event_debug(("%s: dropping illegal header key\n", __func__));
1387 		return (-1);
1388 	}
1389 
1390 	if (!evhttp_header_is_valid_value(value)) {
1391 		event_debug(("%s: dropping illegal header value\n", __func__));
1392 		return (-1);
1393 	}
1394 
1395 	return (evhttp_add_header_internal(headers, key, value));
1396 }
1397 
1398 static int
evhttp_add_header_internal(struct evkeyvalq * headers,const char * key,const char * value)1399 evhttp_add_header_internal(struct evkeyvalq *headers,
1400     const char *key, const char *value)
1401 {
1402 	struct evkeyval *header = calloc(1, sizeof(struct evkeyval));
1403 	if (header == NULL) {
1404 		event_warn("%s: calloc", __func__);
1405 		return (-1);
1406 	}
1407 	if ((header->key = strdup(key)) == NULL) {
1408 		free(header);
1409 		event_warn("%s: strdup", __func__);
1410 		return (-1);
1411 	}
1412 	if ((header->value = strdup(value)) == NULL) {
1413 		free(header->key);
1414 		free(header);
1415 		event_warn("%s: strdup", __func__);
1416 		return (-1);
1417 	}
1418 
1419 	TAILQ_INSERT_TAIL(headers, header, next);
1420 
1421 	return (0);
1422 }
1423 
1424 /*
1425  * Parses header lines from a request or a response into the specified
1426  * request object given an event buffer.
1427  *
1428  * Returns
1429  *   DATA_CORRUPTED      on error
1430  *   MORE_DATA_EXPECTED  when we need to read more headers
1431  *   ALL_DATA_READ       when all headers have been read.
1432  */
1433 
1434 enum message_read_status
evhttp_parse_firstline(struct evhttp_request * req,struct evbuffer * buffer)1435 evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer)
1436 {
1437 	char *line;
1438 	enum message_read_status status = ALL_DATA_READ;
1439 
1440 	line = evbuffer_readline(buffer);
1441 	if (line == NULL)
1442 		return (MORE_DATA_EXPECTED);
1443 
1444 	switch (req->kind) {
1445 	case EVHTTP_REQUEST:
1446 		if (evhttp_parse_request_line(req, line) == -1)
1447 			status = DATA_CORRUPTED;
1448 		break;
1449 	case EVHTTP_RESPONSE:
1450 		if (evhttp_parse_response_line(req, line) == -1)
1451 			status = DATA_CORRUPTED;
1452 		break;
1453 	default:
1454 		status = DATA_CORRUPTED;
1455 	}
1456 
1457 	free(line);
1458 	return (status);
1459 }
1460 
1461 static int
evhttp_append_to_last_header(struct evkeyvalq * headers,const char * line)1462 evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
1463 {
1464 	struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1465 	char *newval;
1466 	size_t old_len, line_len;
1467 
1468 	if (header == NULL)
1469 		return (-1);
1470 
1471 	old_len = strlen(header->value);
1472 	line_len = strlen(line);
1473 
1474 	newval = realloc(header->value, old_len + line_len + 1);
1475 	if (newval == NULL)
1476 		return (-1);
1477 
1478 	memcpy(newval + old_len, line, line_len + 1);
1479 	header->value = newval;
1480 
1481 	return (0);
1482 }
1483 
1484 enum message_read_status
evhttp_parse_headers(struct evhttp_request * req,struct evbuffer * buffer)1485 evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
1486 {
1487 	char *line;
1488 	enum message_read_status status = MORE_DATA_EXPECTED;
1489 
1490 	struct evkeyvalq* headers = req->input_headers;
1491 	while ((line = evbuffer_readline(buffer))
1492 	       != NULL) {
1493 		char *skey, *svalue;
1494 
1495 		if (*line == '\0') { /* Last header - Done */
1496 			status = ALL_DATA_READ;
1497 			free(line);
1498 			break;
1499 		}
1500 
1501 		/* Check if this is a continuation line */
1502 		if (*line == ' ' || *line == '\t') {
1503 			if (evhttp_append_to_last_header(headers, line) == -1)
1504 				goto error;
1505 			free(line);
1506 			continue;
1507 		}
1508 
1509 		/* Processing of header lines */
1510 		svalue = line;
1511 		skey = strsep(&svalue, ":");
1512 		if (svalue == NULL)
1513 			goto error;
1514 
1515 		svalue += strspn(svalue, " ");
1516 
1517 		if (evhttp_add_header(headers, skey, svalue) == -1)
1518 			goto error;
1519 
1520 		free(line);
1521 	}
1522 
1523 	return (status);
1524 
1525  error:
1526 	free(line);
1527 	return (DATA_CORRUPTED);
1528 }
1529 
1530 static int
evhttp_get_body_length(struct evhttp_request * req)1531 evhttp_get_body_length(struct evhttp_request *req)
1532 {
1533 	struct evkeyvalq *headers = req->input_headers;
1534 	const char *content_length;
1535 	const char *connection;
1536 
1537 	content_length = evhttp_find_header(headers, "Content-Length");
1538 	connection = evhttp_find_header(headers, "Connection");
1539 
1540 	if (content_length == NULL && connection == NULL)
1541 		req->ntoread = -1;
1542 	else if (content_length == NULL &&
1543 	    strcasecmp(connection, "Close") != 0) {
1544 		/* Bad combination, we don't know when it will end */
1545 		event_warnx("%s: we got no content length, but the "
1546 		    "server wants to keep the connection open: %s.",
1547 		    __func__, connection);
1548 		return (-1);
1549 	} else if (content_length == NULL) {
1550 		req->ntoread = -1;
1551 	} else {
1552 		char *endp;
1553 		ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
1554 		if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
1555 			event_debug(("%s: illegal content length: %s",
1556 				__func__, content_length));
1557 			return (-1);
1558 		}
1559 		req->ntoread = ntoread;
1560 	}
1561 
1562 	event_debug(("%s: bytes to read: %lld (in buffer %ld)\n",
1563 		__func__, req->ntoread,
1564 		EVBUFFER_LENGTH(req->evcon->input_buffer)));
1565 
1566 	return (0);
1567 }
1568 
1569 static void
evhttp_get_body(struct evhttp_connection * evcon,struct evhttp_request * req)1570 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
1571 {
1572 	const char *xfer_enc;
1573 
1574 	/* If this is a request without a body, then we are done */
1575 	if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) {
1576 		evhttp_connection_done(evcon);
1577 		return;
1578 	}
1579 	evcon->state = EVCON_READING_BODY;
1580 	xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
1581 	if (xfer_enc != NULL && strcasecmp(xfer_enc, "chunked") == 0) {
1582 		req->chunked = 1;
1583 		req->ntoread = -1;
1584 	} else {
1585 		if (evhttp_get_body_length(req) == -1) {
1586 			evhttp_connection_fail(evcon,
1587 			    EVCON_HTTP_INVALID_HEADER);
1588 			return;
1589 		}
1590 	}
1591 	evhttp_read_body(evcon, req);
1592 }
1593 
1594 static void
evhttp_read_firstline(struct evhttp_connection * evcon,struct evhttp_request * req)1595 evhttp_read_firstline(struct evhttp_connection *evcon,
1596 		      struct evhttp_request *req)
1597 {
1598 	enum message_read_status res;
1599 
1600 	res = evhttp_parse_firstline(req, evcon->input_buffer);
1601 	if (res == DATA_CORRUPTED) {
1602 		/* Error while reading, terminate */
1603 		event_debug(("%s: bad header lines on %d\n",
1604 			__func__, evcon->fd));
1605 		evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1606 		return;
1607 	} else if (res == MORE_DATA_EXPECTED) {
1608 		/* Need more header lines */
1609 		evhttp_add_event(&evcon->ev,
1610                     evcon->timeout, HTTP_READ_TIMEOUT);
1611 		return;
1612 	}
1613 
1614 	evcon->state = EVCON_READING_HEADERS;
1615 	evhttp_read_header(evcon, req);
1616 }
1617 
1618 static void
evhttp_read_header(struct evhttp_connection * evcon,struct evhttp_request * req)1619 evhttp_read_header(struct evhttp_connection *evcon, struct evhttp_request *req)
1620 {
1621 	enum message_read_status res;
1622 	int fd = evcon->fd;
1623 
1624 	res = evhttp_parse_headers(req, evcon->input_buffer);
1625 	if (res == DATA_CORRUPTED) {
1626 		/* Error while reading, terminate */
1627 		event_debug(("%s: bad header lines on %d\n", __func__, fd));
1628 		evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1629 		return;
1630 	} else if (res == MORE_DATA_EXPECTED) {
1631 		/* Need more header lines */
1632 		evhttp_add_event(&evcon->ev,
1633 		    evcon->timeout, HTTP_READ_TIMEOUT);
1634 		return;
1635 	}
1636 
1637 	/* Done reading headers, do the real work */
1638 	switch (req->kind) {
1639 	case EVHTTP_REQUEST:
1640 		event_debug(("%s: checking for post data on %d\n",
1641 				__func__, fd));
1642 		evhttp_get_body(evcon, req);
1643 		break;
1644 
1645 	case EVHTTP_RESPONSE:
1646 		if (req->response_code == HTTP_NOCONTENT ||
1647 		    req->response_code == HTTP_NOTMODIFIED ||
1648 		    (req->response_code >= 100 && req->response_code < 200)) {
1649 			event_debug(("%s: skipping body for code %d\n",
1650 					__func__, req->response_code));
1651 			evhttp_connection_done(evcon);
1652 		} else {
1653 			event_debug(("%s: start of read body for %s on %d\n",
1654 				__func__, req->remote_host, fd));
1655 			evhttp_get_body(evcon, req);
1656 		}
1657 		break;
1658 
1659 	default:
1660 		event_warnx("%s: bad header on %d", __func__, fd);
1661 		evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
1662 		break;
1663 	}
1664 }
1665 
1666 /*
1667  * Creates a TCP connection to the specified port and executes a callback
1668  * when finished.  Failure or sucess is indicate by the passed connection
1669  * object.
1670  *
1671  * Although this interface accepts a hostname, it is intended to take
1672  * only numeric hostnames so that non-blocking DNS resolution can
1673  * happen elsewhere.
1674  */
1675 
1676 struct evhttp_connection *
evhttp_connection_new(const char * address,unsigned short port)1677 evhttp_connection_new(const char *address, unsigned short port)
1678 {
1679 	struct evhttp_connection *evcon = NULL;
1680 
1681 	event_debug(("Attempting connection to %s:%d\n", address, port));
1682 
1683 	if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) {
1684 		event_warn("%s: calloc failed", __func__);
1685 		goto error;
1686 	}
1687 
1688 	evcon->fd = -1;
1689 	evcon->port = port;
1690 
1691 	evcon->timeout = -1;
1692 	evcon->retry_cnt = evcon->retry_max = 0;
1693 
1694 	if ((evcon->address = strdup(address)) == NULL) {
1695 		event_warn("%s: strdup failed", __func__);
1696 		goto error;
1697 	}
1698 
1699 	if ((evcon->input_buffer = evbuffer_new()) == NULL) {
1700 		event_warn("%s: evbuffer_new failed", __func__);
1701 		goto error;
1702 	}
1703 
1704 	if ((evcon->output_buffer = evbuffer_new()) == NULL) {
1705 		event_warn("%s: evbuffer_new failed", __func__);
1706 		goto error;
1707 	}
1708 
1709 	evcon->state = EVCON_DISCONNECTED;
1710 	TAILQ_INIT(&evcon->requests);
1711 
1712 	return (evcon);
1713 
1714  error:
1715 	if (evcon != NULL)
1716 		evhttp_connection_free(evcon);
1717 	return (NULL);
1718 }
1719 
evhttp_connection_set_base(struct evhttp_connection * evcon,struct event_base * base)1720 void evhttp_connection_set_base(struct evhttp_connection *evcon,
1721     struct event_base *base)
1722 {
1723 	assert(evcon->base == NULL);
1724 	assert(evcon->state == EVCON_DISCONNECTED);
1725 	evcon->base = base;
1726 }
1727 
1728 void
evhttp_connection_set_timeout(struct evhttp_connection * evcon,int timeout_in_secs)1729 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
1730     int timeout_in_secs)
1731 {
1732 	evcon->timeout = timeout_in_secs;
1733 }
1734 
1735 void
evhttp_connection_set_retries(struct evhttp_connection * evcon,int retry_max)1736 evhttp_connection_set_retries(struct evhttp_connection *evcon,
1737     int retry_max)
1738 {
1739 	evcon->retry_max = retry_max;
1740 }
1741 
1742 void
evhttp_connection_set_closecb(struct evhttp_connection * evcon,void (* cb)(struct evhttp_connection *,void *),void * cbarg)1743 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
1744     void (*cb)(struct evhttp_connection *, void *), void *cbarg)
1745 {
1746 	evcon->closecb = cb;
1747 	evcon->closecb_arg = cbarg;
1748 }
1749 
1750 void
evhttp_connection_get_peer(struct evhttp_connection * evcon,char ** address,u_short * port)1751 evhttp_connection_get_peer(struct evhttp_connection *evcon,
1752     char **address, u_short *port)
1753 {
1754 	*address = evcon->address;
1755 	*port = evcon->port;
1756 }
1757 
1758 int
evhttp_connection_connect(struct evhttp_connection * evcon)1759 evhttp_connection_connect(struct evhttp_connection *evcon)
1760 {
1761 	if (evcon->state == EVCON_CONNECTING)
1762 		return (0);
1763 
1764 	evhttp_connection_reset(evcon);
1765 
1766 	assert(!(evcon->flags & EVHTTP_CON_INCOMING));
1767 	evcon->flags |= EVHTTP_CON_OUTGOING;
1768 
1769 	evcon->fd = bind_socket(
1770 		evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
1771 	if (evcon->fd == -1) {
1772 		event_debug(("%s: failed to bind to \"%s\"",
1773 			__func__, evcon->bind_address));
1774 		return (-1);
1775 	}
1776 
1777 	if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
1778 		EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1;
1779 		return (-1);
1780 	}
1781 
1782 	/* Set up a callback for successful connection setup */
1783 	event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon);
1784 	EVHTTP_BASE_SET(evcon, &evcon->ev);
1785 	evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT);
1786 
1787 	evcon->state = EVCON_CONNECTING;
1788 
1789 	return (0);
1790 }
1791 
1792 /*
1793  * Starts an HTTP request on the provided evhttp_connection object.
1794  * If the connection object is not connected to the web server already,
1795  * this will start the connection.
1796  */
1797 
1798 int
evhttp_make_request(struct evhttp_connection * evcon,struct evhttp_request * req,enum evhttp_cmd_type type,const char * uri)1799 evhttp_make_request(struct evhttp_connection *evcon,
1800     struct evhttp_request *req,
1801     enum evhttp_cmd_type type, const char *uri)
1802 {
1803 	/* We are making a request */
1804 	req->kind = EVHTTP_REQUEST;
1805 	req->type = type;
1806 	if (req->uri != NULL)
1807 		free(req->uri);
1808 	if ((req->uri = strdup(uri)) == NULL)
1809 		event_err(1, "%s: strdup", __func__);
1810 
1811 	/* Set the protocol version if it is not supplied */
1812 	if (!req->major && !req->minor) {
1813 		req->major = 1;
1814 		req->minor = 1;
1815 	}
1816 
1817 	assert(req->evcon == NULL);
1818 	req->evcon = evcon;
1819 	assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
1820 
1821 	TAILQ_INSERT_TAIL(&evcon->requests, req, next);
1822 
1823 	/* If the connection object is not connected; make it so */
1824 	if (!evhttp_connected(evcon))
1825 		return (evhttp_connection_connect(evcon));
1826 
1827 	/*
1828 	 * If it's connected already and we are the first in the queue,
1829 	 * then we can dispatch this request immediately.  Otherwise, it
1830 	 * will be dispatched once the pending requests are completed.
1831 	 */
1832 	if (TAILQ_FIRST(&evcon->requests) == req)
1833 		evhttp_request_dispatch(evcon);
1834 
1835 	return (0);
1836 }
1837 
1838 /*
1839  * Reads data from file descriptor into request structure
1840  * Request structure needs to be set up correctly.
1841  */
1842 
1843 void
evhttp_start_read(struct evhttp_connection * evcon)1844 evhttp_start_read(struct evhttp_connection *evcon)
1845 {
1846 	/* Set up an event to read the headers */
1847 	if (event_initialized(&evcon->ev))
1848 		event_del(&evcon->ev);
1849 	event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
1850 	EVHTTP_BASE_SET(evcon, &evcon->ev);
1851 
1852 	evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
1853 	evcon->state = EVCON_READING_FIRSTLINE;
1854 }
1855 
1856 static void
evhttp_send_done(struct evhttp_connection * evcon,void * arg)1857 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
1858 {
1859 	int need_close;
1860 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1861 	TAILQ_REMOVE(&evcon->requests, req, next);
1862 
1863 	/* delete possible close detection events */
1864 	evhttp_connection_stop_detectclose(evcon);
1865 
1866 	need_close =
1867 	    (req->minor == 0 &&
1868 		!evhttp_is_connection_keepalive(req->input_headers))||
1869 	    evhttp_is_connection_close(req->flags, req->input_headers) ||
1870 	    evhttp_is_connection_close(req->flags, req->output_headers);
1871 
1872 	assert(req->flags & EVHTTP_REQ_OWN_CONNECTION);
1873 	evhttp_request_free(req);
1874 
1875 	if (need_close) {
1876 		evhttp_connection_free(evcon);
1877 		return;
1878 	}
1879 
1880 	/* we have a persistent connection; try to accept another request. */
1881 	if (evhttp_associate_new_request_with_connection(evcon) == -1)
1882 		evhttp_connection_free(evcon);
1883 }
1884 
1885 /*
1886  * Returns an error page.
1887  */
1888 
1889 void
evhttp_send_error(struct evhttp_request * req,int error,const char * reason)1890 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
1891 {
1892 #define ERR_FORMAT "<HTML><HEAD>\n" \
1893 	    "<TITLE>%d %s</TITLE>\n" \
1894 	    "</HEAD><BODY>\n" \
1895 	    "<H1>Method Not Implemented</H1>\n" \
1896 	    "Invalid method in request<P>\n" \
1897 	    "</BODY></HTML>\n"
1898 
1899 	struct evbuffer *buf = evbuffer_new();
1900 
1901 	/* close the connection on error */
1902 	evhttp_add_header(req->output_headers, "Connection", "close");
1903 
1904 	evhttp_response_code(req, error, reason);
1905 
1906 	evbuffer_add_printf(buf, ERR_FORMAT, error, reason);
1907 
1908 	evhttp_send_page(req, buf);
1909 
1910 	evbuffer_free(buf);
1911 #undef ERR_FORMAT
1912 }
1913 
1914 /* Requires that headers and response code are already set up */
1915 
1916 static inline void
evhttp_send(struct evhttp_request * req,struct evbuffer * databuf)1917 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
1918 {
1919 	struct evhttp_connection *evcon = req->evcon;
1920 
1921 	assert(TAILQ_FIRST(&evcon->requests) == req);
1922 
1923 	/* xxx: not sure if we really should expose the data buffer this way */
1924 	if (databuf != NULL)
1925 		evbuffer_add_buffer(req->output_buffer, databuf);
1926 
1927 	/* Adds headers to the response */
1928 	evhttp_make_header(evcon, req);
1929 
1930 	evhttp_write_buffer(evcon, evhttp_send_done, NULL);
1931 }
1932 
1933 void
evhttp_send_reply(struct evhttp_request * req,int code,const char * reason,struct evbuffer * databuf)1934 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
1935     struct evbuffer *databuf)
1936 {
1937 	evhttp_response_code(req, code, reason);
1938 
1939 	evhttp_send(req, databuf);
1940 }
1941 
1942 void
evhttp_send_reply_start(struct evhttp_request * req,int code,const char * reason)1943 evhttp_send_reply_start(struct evhttp_request *req, int code,
1944     const char *reason)
1945 {
1946 	evhttp_response_code(req, code, reason);
1947 	if (req->major == 1 && req->minor == 1) {
1948 		/* use chunked encoding for HTTP/1.1 */
1949 		evhttp_add_header(req->output_headers, "Transfer-Encoding",
1950 		    "chunked");
1951 		req->chunked = 1;
1952 	}
1953 	evhttp_make_header(req->evcon, req);
1954 	evhttp_write_buffer(req->evcon, NULL, NULL);
1955 }
1956 
1957 void
evhttp_send_reply_chunk(struct evhttp_request * req,struct evbuffer * databuf)1958 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
1959 {
1960 	if (req->chunked) {
1961 		evbuffer_add_printf(req->evcon->output_buffer, "%x\r\n",
1962 				    (unsigned)EVBUFFER_LENGTH(databuf));
1963 	}
1964 	evbuffer_add_buffer(req->evcon->output_buffer, databuf);
1965 	if (req->chunked) {
1966 		evbuffer_add(req->evcon->output_buffer, "\r\n", 2);
1967 	}
1968 	evhttp_write_buffer(req->evcon, NULL, NULL);
1969 }
1970 
1971 void
evhttp_send_reply_end(struct evhttp_request * req)1972 evhttp_send_reply_end(struct evhttp_request *req)
1973 {
1974 	struct evhttp_connection *evcon = req->evcon;
1975 
1976 	if (req->chunked) {
1977 		evbuffer_add(req->evcon->output_buffer, "0\r\n\r\n", 5);
1978 		evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
1979 		req->chunked = 0;
1980 	} else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) {
1981 		/* let the connection know that we are done with the request */
1982 		evhttp_send_done(evcon, NULL);
1983 	} else {
1984 		/* make the callback execute after all data has been written */
1985 		evcon->cb = evhttp_send_done;
1986 		evcon->cb_arg = NULL;
1987 	}
1988 }
1989 
1990 void
evhttp_response_code(struct evhttp_request * req,int code,const char * reason)1991 evhttp_response_code(struct evhttp_request *req, int code, const char *reason)
1992 {
1993 	req->kind = EVHTTP_RESPONSE;
1994 	req->response_code = code;
1995 	if (req->response_code_line != NULL)
1996 		free(req->response_code_line);
1997 	req->response_code_line = strdup(reason);
1998 }
1999 
2000 void
evhttp_send_page(struct evhttp_request * req,struct evbuffer * databuf)2001 evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf)
2002 {
2003 	if (!req->major || !req->minor) {
2004 		req->major = 1;
2005 		req->minor = 1;
2006 	}
2007 
2008 	if (req->kind != EVHTTP_RESPONSE)
2009 		evhttp_response_code(req, 200, "OK");
2010 
2011 	evhttp_clear_headers(req->output_headers);
2012 	evhttp_add_header(req->output_headers, "Content-Type", "text/html");
2013 	evhttp_add_header(req->output_headers, "Connection", "close");
2014 
2015 	evhttp_send(req, databuf);
2016 }
2017 
2018 static const char uri_chars[256] = {
2019 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2020 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2021 	0, 1, 0, 0, 1, 0, 0, 1,   1, 1, 1, 1, 1, 1, 1, 1,
2022 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 1, 0, 0,
2023 	/* 64 */
2024 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
2025 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 0, 1,
2026 	0, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
2027 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 1, 0,
2028 	/* 128 */
2029 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2030 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2031 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2032 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2033 	/* 192 */
2034 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2035 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2036 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2037 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
2038 };
2039 
2040 /*
2041  * Helper functions to encode/decode a URI.
2042  * The returned string must be freed by the caller.
2043  */
2044 char *
evhttp_encode_uri(const char * uri)2045 evhttp_encode_uri(const char *uri)
2046 {
2047 	struct evbuffer *buf = evbuffer_new();
2048 	char *p;
2049 
2050 	for (p = (char *)uri; *p != '\0'; p++) {
2051 		if (uri_chars[(u_char)(*p)]) {
2052 			evbuffer_add(buf, p, 1);
2053 		} else {
2054 			evbuffer_add_printf(buf, "%%%02X", (u_char)(*p));
2055 		}
2056 	}
2057 	evbuffer_add(buf, "", 1);
2058 	p = strdup((char *)EVBUFFER_DATA(buf));
2059 	evbuffer_free(buf);
2060 
2061 	return (p);
2062 }
2063 
2064 /*
2065  * @param always_decode_plus: when true we transform plus to space even
2066  *     if we have not seen a ?.
2067  */
2068 static int
evhttp_decode_uri_internal(const char * uri,size_t length,char * ret,int always_decode_plus)2069 evhttp_decode_uri_internal(
2070 	const char *uri, size_t length, char *ret, int always_decode_plus)
2071 {
2072 	char c;
2073 	int i, j, in_query = always_decode_plus;
2074 
2075 	for (i = j = 0; uri[i] != '\0'; i++) {
2076 		c = uri[i];
2077 		if (c == '?') {
2078 			in_query = 1;
2079 		} else if (c == '+' && in_query) {
2080 			c = ' ';
2081 		} else if (c == '%' && isxdigit((unsigned char)uri[i+1]) &&
2082 		    isxdigit((unsigned char)uri[i+2])) {
2083 			char tmp[] = { uri[i+1], uri[i+2], '\0' };
2084 			c = (char)strtol(tmp, NULL, 16);
2085 			i += 2;
2086 		}
2087 		ret[j++] = c;
2088 	}
2089 	ret[j] = '\0';
2090 
2091 	return (j);
2092 }
2093 
2094 char *
evhttp_decode_uri(const char * uri)2095 evhttp_decode_uri(const char *uri)
2096 {
2097 	char *ret;
2098 
2099 	if ((ret = malloc(strlen(uri) + 1)) == NULL)
2100 		event_err(1, "%s: malloc(%lu)", __func__,
2101 			  (unsigned long)(strlen(uri) + 1));
2102 
2103 	evhttp_decode_uri_internal(uri, strlen(uri),
2104 	    ret, 0 /*always_decode_plus*/);
2105 
2106 	return (ret);
2107 }
2108 
2109 /*
2110  * Helper function to parse out arguments in a query.
2111  * The arguments are separated by key and value.
2112  */
2113 
2114 void
evhttp_parse_query(const char * uri,struct evkeyvalq * headers)2115 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
2116 {
2117 	char *line;
2118 	char *argument;
2119 	char *p;
2120 
2121 	TAILQ_INIT(headers);
2122 
2123 	/* No arguments - we are done */
2124 	if (strchr(uri, '?') == NULL)
2125 		return;
2126 
2127 	if ((line = strdup(uri)) == NULL)
2128 		event_err(1, "%s: strdup", __func__);
2129 
2130 
2131 	argument = line;
2132 
2133 	/* We already know that there has to be a ? */
2134 	strsep(&argument, "?");
2135 
2136 	p = argument;
2137 	while (p != NULL && *p != '\0') {
2138 		char *key, *value, *decoded_value;
2139 		argument = strsep(&p, "&");
2140 
2141 		value = argument;
2142 		key = strsep(&value, "=");
2143 		if (value == NULL)
2144 			goto error;
2145 
2146 		if ((decoded_value = malloc(strlen(value) + 1)) == NULL)
2147 			event_err(1, "%s: malloc", __func__);
2148 
2149 		evhttp_decode_uri_internal(value, strlen(value),
2150 		    decoded_value, 1 /*always_decode_plus*/);
2151 		event_debug(("Query Param: %s -> %s\n", key, decoded_value));
2152 		evhttp_add_header_internal(headers, key, decoded_value);
2153 		free(decoded_value);
2154 	}
2155 
2156  error:
2157 	free(line);
2158 }
2159 
2160 static struct evhttp_cb *
evhttp_dispatch_callback(struct httpcbq * callbacks,struct evhttp_request * req)2161 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
2162 {
2163 	struct evhttp_cb *cb;
2164 	size_t offset = 0;
2165 
2166 	/* Test for different URLs */
2167 	char *p = strchr(req->uri, '?');
2168 	if (p != NULL)
2169 		offset = (size_t)(p - req->uri);
2170 
2171 	TAILQ_FOREACH(cb, callbacks, next) {
2172 		int res = 0;
2173 		if (p == NULL) {
2174 			res = strcmp(cb->what, req->uri) == 0;
2175 		} else {
2176 			res = ((strncmp(cb->what, req->uri, offset) == 0) &&
2177 					(cb->what[offset] == '\0'));
2178 		}
2179 
2180 		if (res)
2181 			return (cb);
2182 	}
2183 
2184 	return (NULL);
2185 }
2186 
2187 static void
evhttp_handle_request(struct evhttp_request * req,void * arg)2188 evhttp_handle_request(struct evhttp_request *req, void *arg)
2189 {
2190 	struct evhttp *http = arg;
2191 	struct evhttp_cb *cb = NULL;
2192 
2193 	if (req->uri == NULL) {
2194 		evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
2195 		return;
2196 	}
2197 
2198 	if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
2199 		(*cb->cb)(req, cb->cbarg);
2200 		return;
2201 	}
2202 
2203 	/* Generic call back */
2204 	if (http->gencb) {
2205 		(*http->gencb)(req, http->gencbarg);
2206 		return;
2207 	} else {
2208 		/* We need to send a 404 here */
2209 #define ERR_FORMAT "<html><head>" \
2210 		    "<title>404 Not Found</title>" \
2211 		    "</head><body>" \
2212 		    "<h1>Not Found</h1>" \
2213 		    "<p>The requested URL %s was not found on this server.</p>"\
2214 		    "</body></html>\n"
2215 
2216 		char *escaped_html = evhttp_htmlescape(req->uri);
2217 		struct evbuffer *buf = evbuffer_new();
2218 
2219 		evhttp_response_code(req, HTTP_NOTFOUND, "Not Found");
2220 
2221 		evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
2222 
2223 		free(escaped_html);
2224 
2225 		evhttp_send_page(req, buf);
2226 
2227 		evbuffer_free(buf);
2228 #undef ERR_FORMAT
2229 	}
2230 }
2231 
2232 static void
accept_socket(int fd,short what,void * arg)2233 accept_socket(int fd, short what, void *arg)
2234 {
2235 	struct evhttp *http = arg;
2236 	struct sockaddr_storage ss;
2237 	socklen_t addrlen = sizeof(ss);
2238 	int nfd;
2239 
2240 	if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
2241 		if (errno != EAGAIN && errno != EINTR)
2242 			event_warn("%s: bad accept", __func__);
2243 		return;
2244 	}
2245 	if (evutil_make_socket_nonblocking(nfd) < 0)
2246 		return;
2247 
2248 	evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen);
2249 }
2250 
2251 int
evhttp_bind_socket(struct evhttp * http,const char * address,u_short port)2252 evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
2253 {
2254 	int fd;
2255 	int res;
2256 
2257 	if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
2258 		return (-1);
2259 
2260 	if (listen(fd, 128) == -1) {
2261 		event_warn("%s: listen", __func__);
2262 		EVUTIL_CLOSESOCKET(fd);
2263 		return (-1);
2264 	}
2265 
2266 	res = evhttp_accept_socket(http, fd);
2267 
2268 	if (res != -1)
2269 		event_debug(("Bound to port %d - Awaiting connections ... ",
2270 			port));
2271 
2272 	return (res);
2273 }
2274 
2275 int
evhttp_accept_socket(struct evhttp * http,int fd)2276 evhttp_accept_socket(struct evhttp *http, int fd)
2277 {
2278 	struct evhttp_bound_socket *bound;
2279 	struct event *ev;
2280 	int res;
2281 
2282 	bound = malloc(sizeof(struct evhttp_bound_socket));
2283 	if (bound == NULL)
2284 		return (-1);
2285 
2286 	ev = &bound->bind_ev;
2287 
2288 	/* Schedule the socket for accepting */
2289 	event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http);
2290 	EVHTTP_BASE_SET(http, ev);
2291 
2292 	res = event_add(ev, NULL);
2293 
2294 	if (res == -1) {
2295 		free(bound);
2296 		return (-1);
2297 	}
2298 
2299 	TAILQ_INSERT_TAIL(&http->sockets, bound, next);
2300 
2301 	return (0);
2302 }
2303 
2304 static struct evhttp*
evhttp_new_object(void)2305 evhttp_new_object(void)
2306 {
2307 	struct evhttp *http = NULL;
2308 
2309 	if ((http = calloc(1, sizeof(struct evhttp))) == NULL) {
2310 		event_warn("%s: calloc", __func__);
2311 		return (NULL);
2312 	}
2313 
2314 	http->timeout = -1;
2315 
2316 	TAILQ_INIT(&http->sockets);
2317 	TAILQ_INIT(&http->callbacks);
2318 	TAILQ_INIT(&http->connections);
2319 
2320 	return (http);
2321 }
2322 
2323 struct evhttp *
evhttp_new(struct event_base * base)2324 evhttp_new(struct event_base *base)
2325 {
2326 	struct evhttp *http = evhttp_new_object();
2327 
2328 	http->base = base;
2329 
2330 	return (http);
2331 }
2332 
2333 /*
2334  * Start a web server on the specified address and port.
2335  */
2336 
2337 struct evhttp *
evhttp_start(const char * address,u_short port)2338 evhttp_start(const char *address, u_short port)
2339 {
2340 	struct evhttp *http = evhttp_new_object();
2341 
2342 	if (evhttp_bind_socket(http, address, port) == -1) {
2343 		free(http);
2344 		return (NULL);
2345 	}
2346 
2347 	return (http);
2348 }
2349 
2350 void
evhttp_free(struct evhttp * http)2351 evhttp_free(struct evhttp* http)
2352 {
2353 	struct evhttp_cb *http_cb;
2354 	struct evhttp_connection *evcon;
2355 	struct evhttp_bound_socket *bound;
2356 	int fd;
2357 
2358 	/* Remove the accepting part */
2359 	while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
2360 		TAILQ_REMOVE(&http->sockets, bound, next);
2361 
2362 		fd = bound->bind_ev.ev_fd;
2363 		event_del(&bound->bind_ev);
2364 		EVUTIL_CLOSESOCKET(fd);
2365 
2366 		free(bound);
2367 	}
2368 
2369 	while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
2370 		/* evhttp_connection_free removes the connection */
2371 		evhttp_connection_free(evcon);
2372 	}
2373 
2374 	while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
2375 		TAILQ_REMOVE(&http->callbacks, http_cb, next);
2376 		free(http_cb->what);
2377 		free(http_cb);
2378 	}
2379 
2380 	free(http);
2381 }
2382 
2383 void
evhttp_set_timeout(struct evhttp * http,int timeout_in_secs)2384 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
2385 {
2386 	http->timeout = timeout_in_secs;
2387 }
2388 
2389 void
evhttp_set_cb(struct evhttp * http,const char * uri,void (* cb)(struct evhttp_request *,void *),void * cbarg)2390 evhttp_set_cb(struct evhttp *http, const char *uri,
2391     void (*cb)(struct evhttp_request *, void *), void *cbarg)
2392 {
2393 	struct evhttp_cb *http_cb;
2394 
2395 	if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL)
2396 		event_err(1, "%s: calloc", __func__);
2397 
2398 	http_cb->what = strdup(uri);
2399 	http_cb->cb = cb;
2400 	http_cb->cbarg = cbarg;
2401 
2402 	TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
2403 }
2404 
2405 int
evhttp_del_cb(struct evhttp * http,const char * uri)2406 evhttp_del_cb(struct evhttp *http, const char *uri)
2407 {
2408 	struct evhttp_cb *http_cb;
2409 
2410 	TAILQ_FOREACH(http_cb, &http->callbacks, next) {
2411 		if (strcmp(http_cb->what, uri) == 0)
2412 			break;
2413 	}
2414 	if (http_cb == NULL)
2415 		return (-1);
2416 
2417 	TAILQ_REMOVE(&http->callbacks, http_cb, next);
2418 	free(http_cb->what);
2419 	free(http_cb);
2420 
2421 	return (0);
2422 }
2423 
2424 void
evhttp_set_gencb(struct evhttp * http,void (* cb)(struct evhttp_request *,void *),void * cbarg)2425 evhttp_set_gencb(struct evhttp *http,
2426     void (*cb)(struct evhttp_request *, void *), void *cbarg)
2427 {
2428 	http->gencb = cb;
2429 	http->gencbarg = cbarg;
2430 }
2431 
2432 /*
2433  * Request related functions
2434  */
2435 
2436 struct evhttp_request *
evhttp_request_new(void (* cb)(struct evhttp_request *,void *),void * arg)2437 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
2438 {
2439 	struct evhttp_request *req = NULL;
2440 
2441 	/* Allocate request structure */
2442 	if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) {
2443 		event_warn("%s: calloc", __func__);
2444 		goto error;
2445 	}
2446 
2447 	req->kind = EVHTTP_RESPONSE;
2448 	req->input_headers = calloc(1, sizeof(struct evkeyvalq));
2449 	if (req->input_headers == NULL) {
2450 		event_warn("%s: calloc", __func__);
2451 		goto error;
2452 	}
2453 	TAILQ_INIT(req->input_headers);
2454 
2455 	req->output_headers = calloc(1, sizeof(struct evkeyvalq));
2456 	if (req->output_headers == NULL) {
2457 		event_warn("%s: calloc", __func__);
2458 		goto error;
2459 	}
2460 	TAILQ_INIT(req->output_headers);
2461 
2462 	if ((req->input_buffer = evbuffer_new()) == NULL) {
2463 		event_warn("%s: evbuffer_new", __func__);
2464 		goto error;
2465 	}
2466 
2467 	if ((req->output_buffer = evbuffer_new()) == NULL) {
2468 		event_warn("%s: evbuffer_new", __func__);
2469 		goto error;
2470 	}
2471 
2472 	req->cb = cb;
2473 	req->cb_arg = arg;
2474 
2475 	return (req);
2476 
2477  error:
2478 	if (req != NULL)
2479 		evhttp_request_free(req);
2480 	return (NULL);
2481 }
2482 
2483 void
evhttp_request_free(struct evhttp_request * req)2484 evhttp_request_free(struct evhttp_request *req)
2485 {
2486 	if (req->remote_host != NULL)
2487 		free(req->remote_host);
2488 	if (req->uri != NULL)
2489 		free(req->uri);
2490 	if (req->response_code_line != NULL)
2491 		free(req->response_code_line);
2492 
2493 	evhttp_clear_headers(req->input_headers);
2494 	free(req->input_headers);
2495 
2496 	evhttp_clear_headers(req->output_headers);
2497 	free(req->output_headers);
2498 
2499 	if (req->input_buffer != NULL)
2500 		evbuffer_free(req->input_buffer);
2501 
2502 	if (req->output_buffer != NULL)
2503 		evbuffer_free(req->output_buffer);
2504 
2505 	free(req);
2506 }
2507 
2508 void
evhttp_request_set_chunked_cb(struct evhttp_request * req,void (* cb)(struct evhttp_request *,void *))2509 evhttp_request_set_chunked_cb(struct evhttp_request *req,
2510     void (*cb)(struct evhttp_request *, void *))
2511 {
2512 	req->chunk_cb = cb;
2513 }
2514 
2515 /*
2516  * Allows for inspection of the request URI
2517  */
2518 
2519 const char *
evhttp_request_uri(struct evhttp_request * req)2520 evhttp_request_uri(struct evhttp_request *req) {
2521 	if (req->uri == NULL)
2522 		event_debug(("%s: request %p has no uri\n", __func__, req));
2523 	return (req->uri);
2524 }
2525 
2526 /*
2527  * Takes a file descriptor to read a request from.
2528  * The callback is executed once the whole request has been read.
2529  */
2530 
2531 static struct evhttp_connection*
evhttp_get_request_connection(struct evhttp * http,int fd,struct sockaddr * sa,socklen_t salen)2532 evhttp_get_request_connection(
2533 	struct evhttp* http,
2534 	int fd, struct sockaddr *sa, socklen_t salen)
2535 {
2536 	struct evhttp_connection *evcon;
2537 	char *hostname = NULL, *portname = NULL;
2538 
2539 	name_from_addr(sa, salen, &hostname, &portname);
2540 	if (hostname == NULL || portname == NULL) {
2541 		if (hostname) free(hostname);
2542 		if (portname) free(portname);
2543 		return (NULL);
2544 	}
2545 
2546 	event_debug(("%s: new request from %s:%s on %d\n",
2547 			__func__, hostname, portname, fd));
2548 
2549 	/* we need a connection object to put the http request on */
2550 	evcon = evhttp_connection_new(hostname, atoi(portname));
2551 	free(hostname);
2552 	free(portname);
2553 	if (evcon == NULL)
2554 		return (NULL);
2555 
2556 	/* associate the base if we have one*/
2557 	evhttp_connection_set_base(evcon, http->base);
2558 
2559 	evcon->flags |= EVHTTP_CON_INCOMING;
2560 	evcon->state = EVCON_READING_FIRSTLINE;
2561 
2562 	evcon->fd = fd;
2563 
2564 	return (evcon);
2565 }
2566 
2567 static int
evhttp_associate_new_request_with_connection(struct evhttp_connection * evcon)2568 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
2569 {
2570 	struct evhttp *http = evcon->http_server;
2571 	struct evhttp_request *req;
2572 	if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
2573 		return (-1);
2574 
2575 	req->evcon = evcon;	/* the request ends up owning the connection */
2576 	req->flags |= EVHTTP_REQ_OWN_CONNECTION;
2577 
2578 	TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2579 
2580 	req->kind = EVHTTP_REQUEST;
2581 
2582 	if ((req->remote_host = strdup(evcon->address)) == NULL)
2583 		event_err(1, "%s: strdup", __func__);
2584 	req->remote_port = evcon->port;
2585 
2586 	evhttp_start_read(evcon);
2587 
2588 	return (0);
2589 }
2590 
2591 void
evhttp_get_request(struct evhttp * http,int fd,struct sockaddr * sa,socklen_t salen)2592 evhttp_get_request(struct evhttp *http, int fd,
2593     struct sockaddr *sa, socklen_t salen)
2594 {
2595 	struct evhttp_connection *evcon;
2596 
2597 	evcon = evhttp_get_request_connection(http, fd, sa, salen);
2598 	if (evcon == NULL)
2599 		return;
2600 
2601 	/* the timeout can be used by the server to close idle connections */
2602 	if (http->timeout != -1)
2603 		evhttp_connection_set_timeout(evcon, http->timeout);
2604 
2605 	/*
2606 	 * if we want to accept more than one request on a connection,
2607 	 * we need to know which http server it belongs to.
2608 	 */
2609 	evcon->http_server = http;
2610 	TAILQ_INSERT_TAIL(&http->connections, evcon, next);
2611 
2612 	if (evhttp_associate_new_request_with_connection(evcon) == -1)
2613 		evhttp_connection_free(evcon);
2614 }
2615 
2616 
2617 /*
2618  * Network helper functions that we do not want to export to the rest of
2619  * the world.
2620  */
2621 #if 0 /* Unused */
2622 static struct addrinfo *
2623 addr_from_name(char *address)
2624 {
2625 #ifdef HAVE_GETADDRINFO
2626         struct addrinfo ai, *aitop;
2627         int ai_result;
2628 
2629         memset(&ai, 0, sizeof(ai));
2630         ai.ai_family = AF_INET;
2631         ai.ai_socktype = SOCK_RAW;
2632         ai.ai_flags = 0;
2633         if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) {
2634                 if ( ai_result == EAI_SYSTEM )
2635                         event_warn("getaddrinfo");
2636                 else
2637                         event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
2638         }
2639 
2640 	return (aitop);
2641 #else
2642 	assert(0);
2643 	return NULL; /* XXXXX Use gethostbyname, if this function is ever used. */
2644 #endif
2645 }
2646 #endif
2647 
2648 static void
name_from_addr(struct sockaddr * sa,socklen_t salen,char ** phost,char ** pport)2649 name_from_addr(struct sockaddr *sa, socklen_t salen,
2650     char **phost, char **pport)
2651 {
2652 	char ntop[NI_MAXHOST];
2653 	char strport[NI_MAXSERV];
2654 	int ni_result;
2655 
2656 #ifdef HAVE_GETNAMEINFO
2657 	ni_result = getnameinfo(sa, salen,
2658 		ntop, sizeof(ntop), strport, sizeof(strport),
2659 		NI_NUMERICHOST|NI_NUMERICSERV);
2660 
2661 	if (ni_result != 0) {
2662 		if (ni_result == EAI_SYSTEM)
2663 			event_err(1, "getnameinfo failed");
2664 		else
2665 			event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
2666 		return;
2667 	}
2668 #else
2669 	ni_result = fake_getnameinfo(sa, salen,
2670 		ntop, sizeof(ntop), strport, sizeof(strport),
2671 		NI_NUMERICHOST|NI_NUMERICSERV);
2672 	if (ni_result != 0)
2673 			return;
2674 #endif
2675 	*phost = strdup(ntop);
2676 	*pport = strdup(strport);
2677 }
2678 
2679 /* Create a non-blocking socket and bind it */
2680 /* todo: rename this function */
2681 static int
bind_socket_ai(struct addrinfo * ai,int reuse)2682 bind_socket_ai(struct addrinfo *ai, int reuse)
2683 {
2684         int fd, on = 1, r;
2685 	int serrno;
2686 
2687         /* Create listen socket */
2688         fd = socket(AF_INET, SOCK_STREAM, 0);
2689         if (fd == -1) {
2690                 event_warn("socket");
2691                 return (-1);
2692         }
2693 
2694         if (evutil_make_socket_nonblocking(fd) < 0)
2695                 goto out;
2696 
2697 #ifndef WIN32
2698         if (fcntl(fd, F_SETFD, 1) == -1) {
2699                 event_warn("fcntl(F_SETFD)");
2700                 goto out;
2701         }
2702 #endif
2703 
2704         setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
2705 	if (reuse) {
2706 		setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
2707 		    (void *)&on, sizeof(on));
2708 	}
2709 
2710 	if (ai != NULL) {
2711 		r = bind(fd, ai->ai_addr, ai->ai_addrlen);
2712 		if (r == -1)
2713 			goto out;
2714 	}
2715 
2716 	return (fd);
2717 
2718  out:
2719 	serrno = EVUTIL_SOCKET_ERROR();
2720 	EVUTIL_CLOSESOCKET(fd);
2721 	EVUTIL_SET_SOCKET_ERROR(serrno);
2722 	return (-1);
2723 }
2724 
2725 static struct addrinfo *
make_addrinfo(const char * address,u_short port)2726 make_addrinfo(const char *address, u_short port)
2727 {
2728         struct addrinfo *aitop = NULL;
2729 
2730 #ifdef HAVE_GETADDRINFO
2731         struct addrinfo ai;
2732         char strport[NI_MAXSERV];
2733         int ai_result;
2734 
2735         memset(&ai, 0, sizeof(ai));
2736         ai.ai_family = AF_INET;
2737         ai.ai_socktype = SOCK_STREAM;
2738         ai.ai_flags = AI_PASSIVE;  /* turn NULL host name into INADDR_ANY */
2739         evutil_snprintf(strport, sizeof(strport), "%d", port);
2740         if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
2741                 if ( ai_result == EAI_SYSTEM )
2742                         event_warn("getaddrinfo");
2743                 else
2744                         event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
2745 		return (NULL);
2746         }
2747 #else
2748 	static int cur;
2749 	static struct addrinfo ai[2]; /* We will be returning the address of some of this memory so it has to last even after this call. */
2750 	if (++cur == 2) cur = 0;   /* allow calling this function twice */
2751 
2752 	if (fake_getaddrinfo(address, &ai[cur]) < 0) {
2753 		event_warn("fake_getaddrinfo");
2754 		return (NULL);
2755 	}
2756 	aitop = &ai[cur];
2757 	((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
2758 #endif
2759 
2760 	return (aitop);
2761 }
2762 
2763 static int
bind_socket(const char * address,u_short port,int reuse)2764 bind_socket(const char *address, u_short port, int reuse)
2765 {
2766 	int fd;
2767 	struct addrinfo *aitop = NULL;
2768 
2769 	/* just create an unbound socket */
2770 	if (address == NULL && port == 0)
2771 		return bind_socket_ai(NULL, 0);
2772 
2773 	aitop = make_addrinfo(address, port);
2774 
2775 	if (aitop == NULL)
2776 		return (-1);
2777 
2778 	fd = bind_socket_ai(aitop, reuse);
2779 
2780 #ifdef HAVE_GETADDRINFO
2781 	freeaddrinfo(aitop);
2782 #else
2783 	fake_freeaddrinfo(aitop);
2784 #endif
2785 
2786 	return (fd);
2787 }
2788 
2789 static int
socket_connect(int fd,const char * address,unsigned short port)2790 socket_connect(int fd, const char *address, unsigned short port)
2791 {
2792 	struct addrinfo *ai = make_addrinfo(address, port);
2793 	int res = -1;
2794 
2795 	if (ai == NULL) {
2796 		event_debug(("%s: make_addrinfo: \"%s:%d\"",
2797 			__func__, address, port));
2798 		return (-1);
2799 	}
2800 
2801 	if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
2802 #ifdef WIN32
2803 		int tmp_error = WSAGetLastError();
2804 		if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL &&
2805 		    tmp_error != WSAEINPROGRESS) {
2806 			goto out;
2807 		}
2808 #else
2809 		if (errno != EINPROGRESS) {
2810 			goto out;
2811 		}
2812 #endif
2813 	}
2814 
2815 	/* everything is fine */
2816 	res = 0;
2817 
2818 out:
2819 #ifdef HAVE_GETADDRINFO
2820 	freeaddrinfo(ai);
2821 #else
2822 	fake_freeaddrinfo(ai);
2823 #endif
2824 
2825 	return (res);
2826 }
2827