Upgrade libevent to release-2.1.10-stable

Test: None
Change-Id: I24e4275a07a6dcdd932056c7893a6aabdd786b8a
diff --git a/sample/dns-example.c b/sample/dns-example.c
index fb70566..21a75de 100644
--- a/sample/dns-example.c
+++ b/sample/dns-example.c
@@ -78,6 +78,8 @@
 {
 	const char *name = arg;
 	int i;
+	struct evutil_addrinfo *first_ai = ai;
+
 	if (err) {
 		printf("%s: %s\n", name, evutil_gai_strerror(err));
 	}
@@ -99,6 +101,9 @@
 			printf("[%d] %s: %s\n",i,name,buf);
 		}
 	}
+
+	if (first_ai)
+		evutil_freeaddrinfo(first_ai);
 }
 
 static void
@@ -154,19 +159,19 @@
 		const char *ns;
 	};
 	struct options o;
-	char opt;
+	int opt;
 	struct event_base *event_base = NULL;
 	struct evdns_base *evdns_base = NULL;
 
 	memset(&o, 0, sizeof(o));
-	
+
 	if (c < 2) {
 		fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] [-s ns] hostname\n", v[0]);
 		fprintf(stderr, "syntax: %s [-T]\n", v[0]);
 		return 1;
 	}
 
-	while ((opt = getopt(c, v, "xvc:Ts:")) != -1) {
+	while ((opt = getopt(c, v, "xvc:Ts:g")) != -1) {
 		switch (opt) {
 			case 'x': o.reverse = 1; break;
 			case 'v': ++verbose; break;
@@ -252,6 +257,8 @@
 	}
 	fflush(stdout);
 	event_base_dispatch(event_base);
+	evdns_base_free(evdns_base, 1);
+	event_base_free(event_base);
 	return 0;
 }
 
diff --git a/sample/http-connect.c b/sample/http-connect.c
index a44d001..af2c86a 100644
--- a/sample/http-connect.c
+++ b/sample/http-connect.c
@@ -11,6 +11,7 @@
 #define VERIFY(cond) do {                       \
 	if (!(cond)) {                              \
 		fprintf(stderr, "[error] %s\n", #cond); \
+		exit(EXIT_FAILURE);                     \
 	}                                           \
 } while (0);                                    \
 
@@ -26,8 +27,11 @@
 {
 	ev_ssize_t len;
 	struct evbuffer *evbuf;
+	struct evhttp_connection *evcon;
 
 	VERIFY(req);
+	evcon = evhttp_request_get_connection(req);
+	VERIFY(evcon);
 
 	evbuf = evhttp_request_get_input_buffer(req);
 	len = evbuffer_get_length(evbuf);
@@ -72,7 +76,7 @@
 	}
 
 	{
-		proxy = evhttp_uri_parse(argv[1]);
+		VERIFY(proxy = evhttp_uri_parse(argv[1]));
 		VERIFY(evhttp_uri_get_host(proxy));
 		VERIFY(evhttp_uri_get_port(proxy) > 0);
 	}
diff --git a/sample/http-server.c b/sample/http-server.c
index 579feea..cedb2af 100644
--- a/sample/http-server.c
+++ b/sample/http-server.c
@@ -20,26 +20,39 @@
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <windows.h>
+#include <getopt.h>
 #include <io.h>
 #include <fcntl.h>
 #ifndef S_ISDIR
 #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
 #endif
-#else
+#else /* !_WIN32 */
 #include <sys/stat.h>
 #include <sys/socket.h>
-#include <signal.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <dirent.h>
+#endif /* _WIN32 */
+#include <signal.h>
+
+#ifdef EVENT__HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef EVENT__HAVE_AFUNIX_H
+#include <afunix.h>
 #endif
 
 #include <event2/event.h>
 #include <event2/http.h>
+#include <event2/listener.h>
 #include <event2/buffer.h>
 #include <event2/util.h>
 #include <event2/keyvalq_struct.h>
 
+#ifdef _WIN32
+#include <event2/thread.h>
+#endif /* _WIN32 */
+
 #ifdef EVENT__HAVE_NETINET_IN_H
 #include <netinet/in.h>
 # ifdef _XOPEN_SOURCE_EXTENDED
@@ -63,7 +76,7 @@
 #ifndef O_RDONLY
 #define O_RDONLY _O_RDONLY
 #endif
-#endif
+#endif /* _WIN32 */
 
 char uri_root[512];
 
@@ -86,6 +99,16 @@
 	{ NULL, NULL },
 };
 
+struct options
+{
+	int port;
+	int iocp;
+	int verbose;
+
+	int unlink;
+	const char *unixsock;
+};
+
 /* Try to guess a good content-type for 'path' */
 static const char *
 guess_content_type(const char *path)
@@ -321,42 +344,159 @@
 }
 
 static void
-syntax(void)
+print_usage(FILE *out, const char *prog, int exit_code)
 {
-	fprintf(stdout, "Syntax: http-server <docroot>\n");
+	fprintf(out, "Syntax: [ OPTS ] %s <docroot>\n", prog);
+	fprintf(out, " -p      - port\n");
+	fprintf(out, " -U      - bind to unix socket\n");
+	fprintf(out, " -u      - unlink unix socket before bind\n");
+	fprintf(out, " -I      - IOCP\n");
+	fprintf(out, " -v      - verbosity, enables libevent debug logging too\n");
+	exit(exit_code);
+}
+static struct options
+parse_opts(int argc, char **argv)
+{
+	struct options o;
+	int opt;
+
+	memset(&o, 0, sizeof(o));
+
+	while ((opt = getopt(argc, argv, "hp:U:uIv")) != -1) {
+		switch (opt) {
+			case 'p': o.port = atoi(optarg); break;
+			case 'U': o.unixsock = optarg; break;
+			case 'u': o.unlink = 1; break;
+			case 'I': o.iocp = 1; break;
+			case 'v': ++o.verbose; break;
+			case 'h': print_usage(stdout, argv[0], 0); break;
+			default : fprintf(stderr, "Unknown option %c\n", opt); break;
+		}
+	}
+
+	if (optind >= argc || (argc-optind) > 1) {
+		print_usage(stdout, argv[0], 1);
+	}
+
+	return o;
+}
+
+static void
+do_term(int sig, short events, void *arg)
+{
+	struct event_base *base = arg;
+	event_base_loopbreak(base);
+	fprintf(stderr, "Got %i, Terminating\n", sig);
+}
+
+static int
+display_listen_sock(struct evhttp_bound_socket *handle)
+{
+	struct sockaddr_storage ss;
+	evutil_socket_t fd;
+	ev_socklen_t socklen = sizeof(ss);
+	char addrbuf[128];
+	void *inaddr;
+	const char *addr;
+	int got_port = -1;
+
+	fd = evhttp_bound_socket_get_fd(handle);
+	memset(&ss, 0, sizeof(ss));
+	if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) {
+		perror("getsockname() failed");
+		return 1;
+	}
+
+	if (ss.ss_family == AF_INET) {
+		got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
+		inaddr = &((struct sockaddr_in*)&ss)->sin_addr;
+	} else if (ss.ss_family == AF_INET6) {
+		got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port);
+		inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
+	}
+#ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN
+	else if (ss.ss_family == AF_UNIX) {
+		printf("Listening on <%s>\n", ((struct sockaddr_un*)&ss)->sun_path);
+		return 0;
+	}
+#endif
+	else {
+		fprintf(stderr, "Weird address family %d\n",
+		    ss.ss_family);
+		return 1;
+	}
+
+	addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
+	    sizeof(addrbuf));
+	if (addr) {
+		printf("Listening on %s:%d\n", addr, got_port);
+		evutil_snprintf(uri_root, sizeof(uri_root),
+		    "http://%s:%d",addr,got_port);
+	} else {
+		fprintf(stderr, "evutil_inet_ntop failed\n");
+		return 1;
+	}
+
+	return 0;
 }
 
 int
 main(int argc, char **argv)
 {
-	struct event_base *base;
-	struct evhttp *http;
-	struct evhttp_bound_socket *handle;
+	struct event_config *cfg = NULL;
+	struct event_base *base = NULL;
+	struct evhttp *http = NULL;
+	struct evhttp_bound_socket *handle = NULL;
+	struct evconnlistener *lev = NULL;
+	struct event *term = NULL;
+	struct options o = parse_opts(argc, argv);
+	int ret = 0;
 
-	ev_uint16_t port = 0;
 #ifdef _WIN32
-	WSADATA WSAData;
-	WSAStartup(0x101, &WSAData);
-#else
-	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
-		return (1);
-#endif
-	if (argc < 2) {
-		syntax();
-		return 1;
+	{
+		WORD wVersionRequested;
+		WSADATA wsaData;
+		wVersionRequested = MAKEWORD(2, 2);
+		WSAStartup(wVersionRequested, &wsaData);
 	}
+#else
+	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+		ret = 1;
+		goto err;
+	}
+#endif
 
-	base = event_base_new();
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	/** Read env like in regress */
+	if (o.verbose || getenv("EVENT_DEBUG_LOGGING_ALL"))
+		event_enable_debug_logging(EVENT_DBG_ALL);
+
+	cfg = event_config_new();
+#ifdef _WIN32
+	if (o.iocp) {
+#ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
+		evthread_use_windows_threads();
+		event_config_set_num_cpus_hint(cfg, 8);
+#endif
+		event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+	}
+#endif
+
+	base = event_base_new_with_config(cfg);
 	if (!base) {
 		fprintf(stderr, "Couldn't create an event_base: exiting\n");
-		return 1;
+		ret = 1;
 	}
+	event_config_free(cfg);
+	cfg = NULL;
 
 	/* Create a new evhttp object to handle requests. */
 	http = evhttp_new(base);
 	if (!http) {
 		fprintf(stderr, "couldn't create evhttp. Exiting.\n");
-		return 1;
+		ret = 1;
 	}
 
 	/* The /dump URI will dump all requests to stdout and say 200 ok. */
@@ -366,53 +506,75 @@
 	 * cb.  We can also add callbacks for specific paths. */
 	evhttp_set_gencb(http, send_document_cb, argv[1]);
 
-	/* Now we tell the evhttp what port to listen on */
-	handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", port);
-	if (!handle) {
-		fprintf(stderr, "couldn't bind to port %d. Exiting.\n",
-		    (int)port);
-		return 1;
+	if (o.unixsock) {
+#ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN
+		struct sockaddr_un addr;
+
+		if (o.unlink && (unlink(o.unixsock) && errno != ENOENT)) {
+			perror(o.unixsock);
+			ret = 1;
+			goto err;
+		}
+
+		addr.sun_family = AF_UNIX;
+		strcpy(addr.sun_path, o.unixsock);
+
+		lev = evconnlistener_new_bind(base, NULL, NULL,
+			LEV_OPT_CLOSE_ON_FREE, -1,
+			(struct sockaddr *)&addr, sizeof(addr));
+		if (!lev) {
+			perror("Cannot create listener");
+			ret = 1;
+			goto err;
+		}
+
+		handle = evhttp_bind_listener(http, lev);
+		if (!handle) {
+			fprintf(stderr, "couldn't bind to %s. Exiting.\n", o.unixsock);
+			ret = 1;
+			goto err;
+		}
+#else /* !EVENT__HAVE_STRUCT_SOCKADDR_UN */
+		fprintf(stderr, "-U is not supported on this platform. Exiting.\n");
+		ret = 1;
+		goto err;
+#endif /* EVENT__HAVE_STRUCT_SOCKADDR_UN */
+	}
+	else {
+		handle = evhttp_bind_socket_with_handle(http, "0.0.0.0", o.port);
+		if (!handle) {
+			fprintf(stderr, "couldn't bind to port %d. Exiting.\n", o.port);
+			ret = 1;
+			goto err;
+		}
 	}
 
-	{
-		/* Extract and display the address we're listening on. */
-		struct sockaddr_storage ss;
-		evutil_socket_t fd;
-		ev_socklen_t socklen = sizeof(ss);
-		char addrbuf[128];
-		void *inaddr;
-		const char *addr;
-		int got_port = -1;
-		fd = evhttp_bound_socket_get_fd(handle);
-		memset(&ss, 0, sizeof(ss));
-		if (getsockname(fd, (struct sockaddr *)&ss, &socklen)) {
-			perror("getsockname() failed");
-			return 1;
-		}
-		if (ss.ss_family == AF_INET) {
-			got_port = ntohs(((struct sockaddr_in*)&ss)->sin_port);
-			inaddr = &((struct sockaddr_in*)&ss)->sin_addr;
-		} else if (ss.ss_family == AF_INET6) {
-			got_port = ntohs(((struct sockaddr_in6*)&ss)->sin6_port);
-			inaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
-		} else {
-			fprintf(stderr, "Weird address family %d\n",
-			    ss.ss_family);
-			return 1;
-		}
-		addr = evutil_inet_ntop(ss.ss_family, inaddr, addrbuf,
-		    sizeof(addrbuf));
-		if (addr) {
-			printf("Listening on %s:%d\n", addr, got_port);
-			evutil_snprintf(uri_root, sizeof(uri_root),
-			    "http://%s:%d",addr,got_port);
-		} else {
-			fprintf(stderr, "evutil_inet_ntop failed\n");
-			return 1;
-		}
+	if (display_listen_sock(handle)) {
+		ret = 1;
+		goto err;
 	}
 
+	term = evsignal_new(base, SIGINT, do_term, base);
+	if (!term)
+		goto err;
+	if (event_add(term, NULL))
+		goto err;
+
 	event_base_dispatch(base);
 
-	return 0;
+#ifdef _WIN32
+	WSACleanup();
+#endif
+
+err:
+	if (cfg)
+		event_config_free(cfg);
+	if (http)
+		evhttp_free(http);
+	if (term)
+		event_free(term);
+	if (base)
+		event_base_free(base);
+
+	return ret;
 }
diff --git a/sample/https-client.c b/sample/https-client.c
index 7483956..5869974 100644
--- a/sample/https-client.c
+++ b/sample/https-client.c
@@ -45,7 +45,6 @@
 
 #include "openssl_hostname_validation.h"
 
-static struct event_base *base;
 static int ignore_cert = 0;
 
 static void
@@ -188,10 +187,10 @@
 main(int argc, char **argv)
 {
 	int r;
-
+	struct event_base *base = NULL;
 	struct evhttp_uri *http_uri = NULL;
 	const char *url = NULL, *data_file = NULL;
-	const char *crt = "/etc/ssl/certs/ca-certificates.crt";
+	const char *crt = NULL;
 	const char *scheme, *host, *path, *query;
 	char uri[256];
 	int port;
@@ -312,7 +311,8 @@
 	}
 	uri[sizeof(uri) - 1] = '\0';
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
 	// Initialize OpenSSL
 	SSL_library_init();
 	ERR_load_crypto_strings();
@@ -338,11 +338,19 @@
 #ifndef _WIN32
 	/* TODO: Add certificate loading on Windows as well */
 
-	/* Attempt to use the system's trusted root certificates.
-	 * (This path is only valid for Debian-based systems.) */
-	if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
-		err_openssl("SSL_CTX_load_verify_locations");
-		goto error;
+	if (crt == NULL) {
+		X509_STORE *store;
+		/* Attempt to use the system's trusted root certificates. */
+		store = SSL_CTX_get_cert_store(ssl_ctx);
+		if (X509_STORE_set_default_paths(store) != 1) {
+			err_openssl("X509_STORE_set_default_paths");
+			goto error;
+		}
+	} else {
+		if (SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL) != 1) {
+			err_openssl("SSL_CTX_load_verify_locations");
+			goto error;
+		}
 	}
 	/* Ask OpenSSL to verify the server certificate.  Note that this
 	 * does NOT include verifying that the hostname is correct.
@@ -474,25 +482,29 @@
 		evhttp_connection_free(evcon);
 	if (http_uri)
 		evhttp_uri_free(http_uri);
-	event_base_free(base);
+	if (base)
+		event_base_free(base);
 
 	if (ssl_ctx)
 		SSL_CTX_free(ssl_ctx);
 	if (type == HTTP && ssl)
 		SSL_free(ssl);
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
 	EVP_cleanup();
 	ERR_free_strings();
 
-#ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE
-	ERR_remove_thread_state(NULL);
-#else
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
 	ERR_remove_state(0);
+#else
+	ERR_remove_thread_state(NULL);
 #endif
+
 	CRYPTO_cleanup_all_ex_data();
 
 	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
-#endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */
+#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) */
 
 #ifdef _WIN32
 	WSACleanup();
diff --git a/sample/include.am b/sample/include.am
index d1a7242..cc003b7 100644
--- a/sample/include.am
+++ b/sample/include.am
@@ -16,16 +16,16 @@
 if OPENSSL
 SAMPLES += sample/le-proxy
 sample_le_proxy_SOURCES = sample/le-proxy.c
-sample_le_proxy_LDADD = libevent.la libevent_openssl.la ${OPENSSL_LIBS} ${OPENSSL_LIBADD}
-sample_le_proxy_INCLUDES = $(OPENSSL_INCS)
+sample_le_proxy_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
+sample_le_proxy_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
 
 SAMPLES += sample/https-client
 sample_https_client_SOURCES = \
 	sample/https-client.c \
 	sample/hostcheck.c \
 	sample/openssl_hostname_validation.c
-sample_https_client_LDADD = libevent.la libevent_openssl.la ${OPENSSL_LIBS} ${OPENSSL_LIBADD}
-sample_https_client_INCLUDES = $(OPENSSL_INCS)
+sample_https_client_LDADD = libevent.la libevent_openssl.la $(OPENSSL_LIBS) $(OPENSSL_LIBADD)
+sample_https_client_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
 noinst_HEADERS += \
 	sample/hostcheck.h \
 	sample/openssl_hostname_validation.h
diff --git a/sample/le-proxy.c b/sample/le-proxy.c
index 8d9b529..13e0e2a 100644
--- a/sample/le-proxy.c
+++ b/sample/le-proxy.c
@@ -30,6 +30,7 @@
 #include <event2/listener.h>
 #include <event2/util.h>
 
+#include "util-internal.h"
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
@@ -194,6 +195,7 @@
 			perror("Bufferevent_openssl_new");
 			bufferevent_free(b_out);
 			bufferevent_free(b_in);
+			return;
 		}
 		b_out = b_ssl;
 	}
@@ -214,6 +216,13 @@
 	int use_ssl = 0;
 	struct evconnlistener *listener;
 
+#ifdef _WIN32
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	wVersionRequested = MAKEWORD(2, 2);
+	(void) WSAStartup(wVersionRequested, &wsaData);
+#endif
+
 	if (argc < 3)
 		syntax();
 
@@ -259,7 +268,8 @@
 
 	if (use_ssl) {
 		int r;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
 		SSL_library_init();
 		ERR_load_crypto_strings();
 		SSL_load_error_strings();
@@ -287,5 +297,9 @@
 	evconnlistener_free(listener);
 	event_base_free(base);
 
+#ifdef _WIN32
+	WSACleanup();
+#endif
+
 	return 0;
 }
diff --git a/sample/openssl_hostname_validation.c b/sample/openssl_hostname_validation.c
index 40312f2..4036ccb 100644
--- a/sample/openssl_hostname_validation.c
+++ b/sample/openssl_hostname_validation.c
@@ -48,7 +48,8 @@
 
 #define HOSTNAME_MAX_SIZE 255
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
 #define ASN1_STRING_get0_data ASN1_STRING_data
 #endif
 
diff --git a/sample/time-test.c b/sample/time-test.c
index c94c18a..8d0fd91 100644
--- a/sample/time-test.c
+++ b/sample/time-test.c
@@ -100,6 +100,9 @@
 
 	evutil_gettimeofday(&lasttime, NULL);
 
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
 	event_base_dispatch(base);
 
 	return (0);