xref: /aosp_15_r20/external/libevent/sample/le-proxy.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker   This example code shows how to write an (optionally encrypting) SSL proxy
3*663afb9bSAndroid Build Coastguard Worker   with Libevent's bufferevent layer.
4*663afb9bSAndroid Build Coastguard Worker 
5*663afb9bSAndroid Build Coastguard Worker   XXX It's a little ugly and should probably be cleaned up.
6*663afb9bSAndroid Build Coastguard Worker  */
7*663afb9bSAndroid Build Coastguard Worker 
8*663afb9bSAndroid Build Coastguard Worker // Get rid of OSX 10.7 and greater deprecation warnings.
9*663afb9bSAndroid Build Coastguard Worker #if defined(__APPLE__) && defined(__clang__)
10*663afb9bSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
11*663afb9bSAndroid Build Coastguard Worker #endif
12*663afb9bSAndroid Build Coastguard Worker 
13*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
14*663afb9bSAndroid Build Coastguard Worker #include <assert.h>
15*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
16*663afb9bSAndroid Build Coastguard Worker #include <string.h>
17*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
18*663afb9bSAndroid Build Coastguard Worker 
19*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
20*663afb9bSAndroid Build Coastguard Worker #include <winsock2.h>
21*663afb9bSAndroid Build Coastguard Worker #include <ws2tcpip.h>
22*663afb9bSAndroid Build Coastguard Worker #else
23*663afb9bSAndroid Build Coastguard Worker #include <sys/socket.h>
24*663afb9bSAndroid Build Coastguard Worker #include <netinet/in.h>
25*663afb9bSAndroid Build Coastguard Worker #endif
26*663afb9bSAndroid Build Coastguard Worker 
27*663afb9bSAndroid Build Coastguard Worker #include <event2/bufferevent_ssl.h>
28*663afb9bSAndroid Build Coastguard Worker #include <event2/bufferevent.h>
29*663afb9bSAndroid Build Coastguard Worker #include <event2/buffer.h>
30*663afb9bSAndroid Build Coastguard Worker #include <event2/listener.h>
31*663afb9bSAndroid Build Coastguard Worker #include <event2/util.h>
32*663afb9bSAndroid Build Coastguard Worker 
33*663afb9bSAndroid Build Coastguard Worker #include "util-internal.h"
34*663afb9bSAndroid Build Coastguard Worker #include <openssl/ssl.h>
35*663afb9bSAndroid Build Coastguard Worker #include <openssl/err.h>
36*663afb9bSAndroid Build Coastguard Worker #include <openssl/rand.h>
37*663afb9bSAndroid Build Coastguard Worker #include "openssl-compat.h"
38*663afb9bSAndroid Build Coastguard Worker 
39*663afb9bSAndroid Build Coastguard Worker static struct event_base *base;
40*663afb9bSAndroid Build Coastguard Worker static struct sockaddr_storage listen_on_addr;
41*663afb9bSAndroid Build Coastguard Worker static struct sockaddr_storage connect_to_addr;
42*663afb9bSAndroid Build Coastguard Worker static int connect_to_addrlen;
43*663afb9bSAndroid Build Coastguard Worker static int use_wrapper = 1;
44*663afb9bSAndroid Build Coastguard Worker 
45*663afb9bSAndroid Build Coastguard Worker static SSL_CTX *ssl_ctx = NULL;
46*663afb9bSAndroid Build Coastguard Worker 
47*663afb9bSAndroid Build Coastguard Worker #define MAX_OUTPUT (512*1024)
48*663afb9bSAndroid Build Coastguard Worker 
49*663afb9bSAndroid Build Coastguard Worker static void drained_writecb(struct bufferevent *bev, void *ctx);
50*663afb9bSAndroid Build Coastguard Worker static void eventcb(struct bufferevent *bev, short what, void *ctx);
51*663afb9bSAndroid Build Coastguard Worker 
52*663afb9bSAndroid Build Coastguard Worker static void
readcb(struct bufferevent * bev,void * ctx)53*663afb9bSAndroid Build Coastguard Worker readcb(struct bufferevent *bev, void *ctx)
54*663afb9bSAndroid Build Coastguard Worker {
55*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *partner = ctx;
56*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer *src, *dst;
57*663afb9bSAndroid Build Coastguard Worker 	size_t len;
58*663afb9bSAndroid Build Coastguard Worker 	src = bufferevent_get_input(bev);
59*663afb9bSAndroid Build Coastguard Worker 	len = evbuffer_get_length(src);
60*663afb9bSAndroid Build Coastguard Worker 	if (!partner) {
61*663afb9bSAndroid Build Coastguard Worker 		evbuffer_drain(src, len);
62*663afb9bSAndroid Build Coastguard Worker 		return;
63*663afb9bSAndroid Build Coastguard Worker 	}
64*663afb9bSAndroid Build Coastguard Worker 	dst = bufferevent_get_output(partner);
65*663afb9bSAndroid Build Coastguard Worker 	evbuffer_add_buffer(dst, src);
66*663afb9bSAndroid Build Coastguard Worker 
67*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
68*663afb9bSAndroid Build Coastguard Worker 		/* We're giving the other side data faster than it can
69*663afb9bSAndroid Build Coastguard Worker 		 * pass it on.  Stop reading here until we have drained the
70*663afb9bSAndroid Build Coastguard Worker 		 * other side to MAX_OUTPUT/2 bytes. */
71*663afb9bSAndroid Build Coastguard Worker 		bufferevent_setcb(partner, readcb, drained_writecb,
72*663afb9bSAndroid Build Coastguard Worker 		    eventcb, bev);
73*663afb9bSAndroid Build Coastguard Worker 		bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
74*663afb9bSAndroid Build Coastguard Worker 		    MAX_OUTPUT);
75*663afb9bSAndroid Build Coastguard Worker 		bufferevent_disable(bev, EV_READ);
76*663afb9bSAndroid Build Coastguard Worker 	}
77*663afb9bSAndroid Build Coastguard Worker }
78*663afb9bSAndroid Build Coastguard Worker 
79*663afb9bSAndroid Build Coastguard Worker static void
drained_writecb(struct bufferevent * bev,void * ctx)80*663afb9bSAndroid Build Coastguard Worker drained_writecb(struct bufferevent *bev, void *ctx)
81*663afb9bSAndroid Build Coastguard Worker {
82*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *partner = ctx;
83*663afb9bSAndroid Build Coastguard Worker 
84*663afb9bSAndroid Build Coastguard Worker 	/* We were choking the other side until we drained our outbuf a bit.
85*663afb9bSAndroid Build Coastguard Worker 	 * Now it seems drained. */
86*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setcb(bev, readcb, NULL, eventcb, partner);
87*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
88*663afb9bSAndroid Build Coastguard Worker 	if (partner)
89*663afb9bSAndroid Build Coastguard Worker 		bufferevent_enable(partner, EV_READ);
90*663afb9bSAndroid Build Coastguard Worker }
91*663afb9bSAndroid Build Coastguard Worker 
92*663afb9bSAndroid Build Coastguard Worker static void
close_on_finished_writecb(struct bufferevent * bev,void * ctx)93*663afb9bSAndroid Build Coastguard Worker close_on_finished_writecb(struct bufferevent *bev, void *ctx)
94*663afb9bSAndroid Build Coastguard Worker {
95*663afb9bSAndroid Build Coastguard Worker 	struct evbuffer *b = bufferevent_get_output(bev);
96*663afb9bSAndroid Build Coastguard Worker 
97*663afb9bSAndroid Build Coastguard Worker 	if (evbuffer_get_length(b) == 0) {
98*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(bev);
99*663afb9bSAndroid Build Coastguard Worker 	}
100*663afb9bSAndroid Build Coastguard Worker }
101*663afb9bSAndroid Build Coastguard Worker 
102*663afb9bSAndroid Build Coastguard Worker static void
eventcb(struct bufferevent * bev,short what,void * ctx)103*663afb9bSAndroid Build Coastguard Worker eventcb(struct bufferevent *bev, short what, void *ctx)
104*663afb9bSAndroid Build Coastguard Worker {
105*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *partner = ctx;
106*663afb9bSAndroid Build Coastguard Worker 
107*663afb9bSAndroid Build Coastguard Worker 	if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
108*663afb9bSAndroid Build Coastguard Worker 		if (what & BEV_EVENT_ERROR) {
109*663afb9bSAndroid Build Coastguard Worker 			unsigned long err;
110*663afb9bSAndroid Build Coastguard Worker 			while ((err = (bufferevent_get_openssl_error(bev)))) {
111*663afb9bSAndroid Build Coastguard Worker 				const char *msg = (const char*)
112*663afb9bSAndroid Build Coastguard Worker 				    ERR_reason_error_string(err);
113*663afb9bSAndroid Build Coastguard Worker 				const char *lib = (const char*)
114*663afb9bSAndroid Build Coastguard Worker 				    ERR_lib_error_string(err);
115*663afb9bSAndroid Build Coastguard Worker 				const char *func = (const char*)
116*663afb9bSAndroid Build Coastguard Worker 				    ERR_func_error_string(err);
117*663afb9bSAndroid Build Coastguard Worker 				fprintf(stderr,
118*663afb9bSAndroid Build Coastguard Worker 				    "%s in %s %s\n", msg, lib, func);
119*663afb9bSAndroid Build Coastguard Worker 			}
120*663afb9bSAndroid Build Coastguard Worker 			if (errno)
121*663afb9bSAndroid Build Coastguard Worker 				perror("connection error");
122*663afb9bSAndroid Build Coastguard Worker 		}
123*663afb9bSAndroid Build Coastguard Worker 
124*663afb9bSAndroid Build Coastguard Worker 		if (partner) {
125*663afb9bSAndroid Build Coastguard Worker 			/* Flush all pending data */
126*663afb9bSAndroid Build Coastguard Worker 			readcb(bev, ctx);
127*663afb9bSAndroid Build Coastguard Worker 
128*663afb9bSAndroid Build Coastguard Worker 			if (evbuffer_get_length(
129*663afb9bSAndroid Build Coastguard Worker 				    bufferevent_get_output(partner))) {
130*663afb9bSAndroid Build Coastguard Worker 				/* We still have to flush data from the other
131*663afb9bSAndroid Build Coastguard Worker 				 * side, but when that's done, close the other
132*663afb9bSAndroid Build Coastguard Worker 				 * side. */
133*663afb9bSAndroid Build Coastguard Worker 				bufferevent_setcb(partner,
134*663afb9bSAndroid Build Coastguard Worker 				    NULL, close_on_finished_writecb,
135*663afb9bSAndroid Build Coastguard Worker 				    eventcb, NULL);
136*663afb9bSAndroid Build Coastguard Worker 				bufferevent_disable(partner, EV_READ);
137*663afb9bSAndroid Build Coastguard Worker 			} else {
138*663afb9bSAndroid Build Coastguard Worker 				/* We have nothing left to say to the other
139*663afb9bSAndroid Build Coastguard Worker 				 * side; close it. */
140*663afb9bSAndroid Build Coastguard Worker 				bufferevent_free(partner);
141*663afb9bSAndroid Build Coastguard Worker 			}
142*663afb9bSAndroid Build Coastguard Worker 		}
143*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(bev);
144*663afb9bSAndroid Build Coastguard Worker 	}
145*663afb9bSAndroid Build Coastguard Worker }
146*663afb9bSAndroid Build Coastguard Worker 
147*663afb9bSAndroid Build Coastguard Worker static void
syntax(void)148*663afb9bSAndroid Build Coastguard Worker syntax(void)
149*663afb9bSAndroid Build Coastguard Worker {
150*663afb9bSAndroid Build Coastguard Worker 	fputs("Syntax:\n", stderr);
151*663afb9bSAndroid Build Coastguard Worker 	fputs("   le-proxy [-s] [-W] <listen-on-addr> <connect-to-addr>\n", stderr);
152*663afb9bSAndroid Build Coastguard Worker 	fputs("Example:\n", stderr);
153*663afb9bSAndroid Build Coastguard Worker 	fputs("   le-proxy 127.0.0.1:8888 1.2.3.4:80\n", stderr);
154*663afb9bSAndroid Build Coastguard Worker 
155*663afb9bSAndroid Build Coastguard Worker 	exit(1);
156*663afb9bSAndroid Build Coastguard Worker }
157*663afb9bSAndroid Build Coastguard Worker 
158*663afb9bSAndroid Build Coastguard Worker static void
accept_cb(struct evconnlistener * listener,evutil_socket_t fd,struct sockaddr * a,int slen,void * p)159*663afb9bSAndroid Build Coastguard Worker accept_cb(struct evconnlistener *listener, evutil_socket_t fd,
160*663afb9bSAndroid Build Coastguard Worker     struct sockaddr *a, int slen, void *p)
161*663afb9bSAndroid Build Coastguard Worker {
162*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *b_out, *b_in;
163*663afb9bSAndroid Build Coastguard Worker 	/* Create two linked bufferevent objects: one to connect, one for the
164*663afb9bSAndroid Build Coastguard Worker 	 * new connection */
165*663afb9bSAndroid Build Coastguard Worker 	b_in = bufferevent_socket_new(base, fd,
166*663afb9bSAndroid Build Coastguard Worker 	    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
167*663afb9bSAndroid Build Coastguard Worker 
168*663afb9bSAndroid Build Coastguard Worker 	if (!ssl_ctx || use_wrapper)
169*663afb9bSAndroid Build Coastguard Worker 		b_out = bufferevent_socket_new(base, -1,
170*663afb9bSAndroid Build Coastguard Worker 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
171*663afb9bSAndroid Build Coastguard Worker 	else {
172*663afb9bSAndroid Build Coastguard Worker 		SSL *ssl = SSL_new(ssl_ctx);
173*663afb9bSAndroid Build Coastguard Worker 		b_out = bufferevent_openssl_socket_new(base, -1, ssl,
174*663afb9bSAndroid Build Coastguard Worker 		    BUFFEREVENT_SSL_CONNECTING,
175*663afb9bSAndroid Build Coastguard Worker 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
176*663afb9bSAndroid Build Coastguard Worker 	}
177*663afb9bSAndroid Build Coastguard Worker 
178*663afb9bSAndroid Build Coastguard Worker 	assert(b_in && b_out);
179*663afb9bSAndroid Build Coastguard Worker 
180*663afb9bSAndroid Build Coastguard Worker 	if (bufferevent_socket_connect(b_out,
181*663afb9bSAndroid Build Coastguard Worker 		(struct sockaddr*)&connect_to_addr, connect_to_addrlen)<0) {
182*663afb9bSAndroid Build Coastguard Worker 		perror("bufferevent_socket_connect");
183*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(b_out);
184*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(b_in);
185*663afb9bSAndroid Build Coastguard Worker 		return;
186*663afb9bSAndroid Build Coastguard Worker 	}
187*663afb9bSAndroid Build Coastguard Worker 
188*663afb9bSAndroid Build Coastguard Worker 	if (ssl_ctx && use_wrapper) {
189*663afb9bSAndroid Build Coastguard Worker 		struct bufferevent *b_ssl;
190*663afb9bSAndroid Build Coastguard Worker 		SSL *ssl = SSL_new(ssl_ctx);
191*663afb9bSAndroid Build Coastguard Worker 		b_ssl = bufferevent_openssl_filter_new(base,
192*663afb9bSAndroid Build Coastguard Worker 		    b_out, ssl, BUFFEREVENT_SSL_CONNECTING,
193*663afb9bSAndroid Build Coastguard Worker 		    BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
194*663afb9bSAndroid Build Coastguard Worker 		if (!b_ssl) {
195*663afb9bSAndroid Build Coastguard Worker 			perror("Bufferevent_openssl_new");
196*663afb9bSAndroid Build Coastguard Worker 			bufferevent_free(b_out);
197*663afb9bSAndroid Build Coastguard Worker 			bufferevent_free(b_in);
198*663afb9bSAndroid Build Coastguard Worker 			return;
199*663afb9bSAndroid Build Coastguard Worker 		}
200*663afb9bSAndroid Build Coastguard Worker 		b_out = b_ssl;
201*663afb9bSAndroid Build Coastguard Worker 	}
202*663afb9bSAndroid Build Coastguard Worker 
203*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setcb(b_in, readcb, NULL, eventcb, b_out);
204*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setcb(b_out, readcb, NULL, eventcb, b_in);
205*663afb9bSAndroid Build Coastguard Worker 
206*663afb9bSAndroid Build Coastguard Worker 	bufferevent_enable(b_in, EV_READ|EV_WRITE);
207*663afb9bSAndroid Build Coastguard Worker 	bufferevent_enable(b_out, EV_READ|EV_WRITE);
208*663afb9bSAndroid Build Coastguard Worker }
209*663afb9bSAndroid Build Coastguard Worker 
210*663afb9bSAndroid Build Coastguard Worker int
main(int argc,char ** argv)211*663afb9bSAndroid Build Coastguard Worker main(int argc, char **argv)
212*663afb9bSAndroid Build Coastguard Worker {
213*663afb9bSAndroid Build Coastguard Worker 	int i;
214*663afb9bSAndroid Build Coastguard Worker 	int socklen;
215*663afb9bSAndroid Build Coastguard Worker 
216*663afb9bSAndroid Build Coastguard Worker 	int use_ssl = 0;
217*663afb9bSAndroid Build Coastguard Worker 	struct evconnlistener *listener;
218*663afb9bSAndroid Build Coastguard Worker 
219*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
220*663afb9bSAndroid Build Coastguard Worker 	WORD wVersionRequested;
221*663afb9bSAndroid Build Coastguard Worker 	WSADATA wsaData;
222*663afb9bSAndroid Build Coastguard Worker 	wVersionRequested = MAKEWORD(2, 2);
223*663afb9bSAndroid Build Coastguard Worker 	(void) WSAStartup(wVersionRequested, &wsaData);
224*663afb9bSAndroid Build Coastguard Worker #endif
225*663afb9bSAndroid Build Coastguard Worker 
226*663afb9bSAndroid Build Coastguard Worker 	if (argc < 3)
227*663afb9bSAndroid Build Coastguard Worker 		syntax();
228*663afb9bSAndroid Build Coastguard Worker 
229*663afb9bSAndroid Build Coastguard Worker 	for (i=1; i < argc; ++i) {
230*663afb9bSAndroid Build Coastguard Worker 		if (!strcmp(argv[i], "-s")) {
231*663afb9bSAndroid Build Coastguard Worker 			use_ssl = 1;
232*663afb9bSAndroid Build Coastguard Worker 		} else if (!strcmp(argv[i], "-W")) {
233*663afb9bSAndroid Build Coastguard Worker 			use_wrapper = 0;
234*663afb9bSAndroid Build Coastguard Worker 		} else if (argv[i][0] == '-') {
235*663afb9bSAndroid Build Coastguard Worker 			syntax();
236*663afb9bSAndroid Build Coastguard Worker 		} else
237*663afb9bSAndroid Build Coastguard Worker 			break;
238*663afb9bSAndroid Build Coastguard Worker 	}
239*663afb9bSAndroid Build Coastguard Worker 
240*663afb9bSAndroid Build Coastguard Worker 	if (i+2 != argc)
241*663afb9bSAndroid Build Coastguard Worker 		syntax();
242*663afb9bSAndroid Build Coastguard Worker 
243*663afb9bSAndroid Build Coastguard Worker 	memset(&listen_on_addr, 0, sizeof(listen_on_addr));
244*663afb9bSAndroid Build Coastguard Worker 	socklen = sizeof(listen_on_addr);
245*663afb9bSAndroid Build Coastguard Worker 	if (evutil_parse_sockaddr_port(argv[i],
246*663afb9bSAndroid Build Coastguard Worker 		(struct sockaddr*)&listen_on_addr, &socklen)<0) {
247*663afb9bSAndroid Build Coastguard Worker 		int p = atoi(argv[i]);
248*663afb9bSAndroid Build Coastguard Worker 		struct sockaddr_in *sin = (struct sockaddr_in*)&listen_on_addr;
249*663afb9bSAndroid Build Coastguard Worker 		if (p < 1 || p > 65535)
250*663afb9bSAndroid Build Coastguard Worker 			syntax();
251*663afb9bSAndroid Build Coastguard Worker 		sin->sin_port = htons(p);
252*663afb9bSAndroid Build Coastguard Worker 		sin->sin_addr.s_addr = htonl(0x7f000001);
253*663afb9bSAndroid Build Coastguard Worker 		sin->sin_family = AF_INET;
254*663afb9bSAndroid Build Coastguard Worker 		socklen = sizeof(struct sockaddr_in);
255*663afb9bSAndroid Build Coastguard Worker 	}
256*663afb9bSAndroid Build Coastguard Worker 
257*663afb9bSAndroid Build Coastguard Worker 	memset(&connect_to_addr, 0, sizeof(connect_to_addr));
258*663afb9bSAndroid Build Coastguard Worker 	connect_to_addrlen = sizeof(connect_to_addr);
259*663afb9bSAndroid Build Coastguard Worker 	if (evutil_parse_sockaddr_port(argv[i+1],
260*663afb9bSAndroid Build Coastguard Worker 		(struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0)
261*663afb9bSAndroid Build Coastguard Worker 		syntax();
262*663afb9bSAndroid Build Coastguard Worker 
263*663afb9bSAndroid Build Coastguard Worker 	base = event_base_new();
264*663afb9bSAndroid Build Coastguard Worker 	if (!base) {
265*663afb9bSAndroid Build Coastguard Worker 		perror("event_base_new()");
266*663afb9bSAndroid Build Coastguard Worker 		return 1;
267*663afb9bSAndroid Build Coastguard Worker 	}
268*663afb9bSAndroid Build Coastguard Worker 
269*663afb9bSAndroid Build Coastguard Worker 	if (use_ssl) {
270*663afb9bSAndroid Build Coastguard Worker 		int r;
271*663afb9bSAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
272*663afb9bSAndroid Build Coastguard Worker 	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
273*663afb9bSAndroid Build Coastguard Worker 		SSL_library_init();
274*663afb9bSAndroid Build Coastguard Worker 		ERR_load_crypto_strings();
275*663afb9bSAndroid Build Coastguard Worker 		SSL_load_error_strings();
276*663afb9bSAndroid Build Coastguard Worker 		OpenSSL_add_all_algorithms();
277*663afb9bSAndroid Build Coastguard Worker #endif
278*663afb9bSAndroid Build Coastguard Worker 		r = RAND_poll();
279*663afb9bSAndroid Build Coastguard Worker 		if (r == 0) {
280*663afb9bSAndroid Build Coastguard Worker 			fprintf(stderr, "RAND_poll() failed.\n");
281*663afb9bSAndroid Build Coastguard Worker 			return 1;
282*663afb9bSAndroid Build Coastguard Worker 		}
283*663afb9bSAndroid Build Coastguard Worker 		ssl_ctx = SSL_CTX_new(TLS_method());
284*663afb9bSAndroid Build Coastguard Worker 	}
285*663afb9bSAndroid Build Coastguard Worker 
286*663afb9bSAndroid Build Coastguard Worker 	listener = evconnlistener_new_bind(base, accept_cb, NULL,
287*663afb9bSAndroid Build Coastguard Worker 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE,
288*663afb9bSAndroid Build Coastguard Worker 	    -1, (struct sockaddr*)&listen_on_addr, socklen);
289*663afb9bSAndroid Build Coastguard Worker 
290*663afb9bSAndroid Build Coastguard Worker 	if (! listener) {
291*663afb9bSAndroid Build Coastguard Worker 		fprintf(stderr, "Couldn't open listener.\n");
292*663afb9bSAndroid Build Coastguard Worker 		event_base_free(base);
293*663afb9bSAndroid Build Coastguard Worker 		return 1;
294*663afb9bSAndroid Build Coastguard Worker 	}
295*663afb9bSAndroid Build Coastguard Worker 	event_base_dispatch(base);
296*663afb9bSAndroid Build Coastguard Worker 
297*663afb9bSAndroid Build Coastguard Worker 	evconnlistener_free(listener);
298*663afb9bSAndroid Build Coastguard Worker 	event_base_free(base);
299*663afb9bSAndroid Build Coastguard Worker 
300*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
301*663afb9bSAndroid Build Coastguard Worker 	WSACleanup();
302*663afb9bSAndroid Build Coastguard Worker #endif
303*663afb9bSAndroid Build Coastguard Worker 
304*663afb9bSAndroid Build Coastguard Worker 	return 0;
305*663afb9bSAndroid Build Coastguard Worker }
306