xref: /aosp_15_r20/external/libevent/test/test-fdleak.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker  * Copyright (c) 2012 Ross Lagerwall <[email protected]>
3*663afb9bSAndroid Build Coastguard Worker  *
4*663afb9bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
5*663afb9bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
6*663afb9bSAndroid Build Coastguard Worker  * are met:
7*663afb9bSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
8*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
9*663afb9bSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
10*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
11*663afb9bSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
12*663afb9bSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
13*663afb9bSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
14*663afb9bSAndroid Build Coastguard Worker  *
15*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*663afb9bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*663afb9bSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*663afb9bSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*663afb9bSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*663afb9bSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*663afb9bSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*663afb9bSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*663afb9bSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*663afb9bSAndroid Build Coastguard Worker  */
26*663afb9bSAndroid Build Coastguard Worker 
27*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
28*663afb9bSAndroid Build Coastguard Worker 
29*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
30*663afb9bSAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
31*663afb9bSAndroid Build Coastguard Worker #include <windows.h>
32*663afb9bSAndroid Build Coastguard Worker #endif
33*663afb9bSAndroid Build Coastguard Worker #include <string.h>
34*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
35*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
36*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_TIME_H
37*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
38*663afb9bSAndroid Build Coastguard Worker #endif
39*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_RESOURCE_H
40*663afb9bSAndroid Build Coastguard Worker #include <sys/resource.h>
41*663afb9bSAndroid Build Coastguard Worker #endif
42*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_NETINET_IN_H
43*663afb9bSAndroid Build Coastguard Worker #include <netinet/in.h>
44*663afb9bSAndroid Build Coastguard Worker #endif
45*663afb9bSAndroid Build Coastguard Worker 
46*663afb9bSAndroid Build Coastguard Worker #include "event2/event.h"
47*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent.h"
48*663afb9bSAndroid Build Coastguard Worker #include "event2/buffer.h"
49*663afb9bSAndroid Build Coastguard Worker #include "event2/listener.h"
50*663afb9bSAndroid Build Coastguard Worker 
51*663afb9bSAndroid Build Coastguard Worker /* Number of requests to make. Setting this too high might result in the machine
52*663afb9bSAndroid Build Coastguard Worker    running out of ephemeral ports */
53*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
54*663afb9bSAndroid Build Coastguard Worker #define MAX_REQUESTS 1000
55*663afb9bSAndroid Build Coastguard Worker #else
56*663afb9bSAndroid Build Coastguard Worker #define MAX_REQUESTS 4000
57*663afb9bSAndroid Build Coastguard Worker #endif
58*663afb9bSAndroid Build Coastguard Worker 
59*663afb9bSAndroid Build Coastguard Worker /* Provide storage for the address, both for the server & the clients */
60*663afb9bSAndroid Build Coastguard Worker static struct sockaddr_in saddr;
61*663afb9bSAndroid Build Coastguard Worker 
62*663afb9bSAndroid Build Coastguard Worker /* Number of sucessful requests so far */
63*663afb9bSAndroid Build Coastguard Worker static int num_requests;
64*663afb9bSAndroid Build Coastguard Worker 
65*663afb9bSAndroid Build Coastguard Worker static void start_client(struct event_base *base);
66*663afb9bSAndroid Build Coastguard Worker 
67*663afb9bSAndroid Build Coastguard Worker static void
my_perror(const char * s)68*663afb9bSAndroid Build Coastguard Worker my_perror(const char *s)
69*663afb9bSAndroid Build Coastguard Worker {
70*663afb9bSAndroid Build Coastguard Worker 	fprintf(stderr, "%s: %s",
71*663afb9bSAndroid Build Coastguard Worker 	    s, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
72*663afb9bSAndroid Build Coastguard Worker }
73*663afb9bSAndroid Build Coastguard Worker 
74*663afb9bSAndroid Build Coastguard Worker /*
75*663afb9bSAndroid Build Coastguard Worker ===============================================
76*663afb9bSAndroid Build Coastguard Worker Server functions
77*663afb9bSAndroid Build Coastguard Worker ===============================================
78*663afb9bSAndroid Build Coastguard Worker */
79*663afb9bSAndroid Build Coastguard Worker 
80*663afb9bSAndroid Build Coastguard Worker /* Read a byte from the client and write it back */
81*663afb9bSAndroid Build Coastguard Worker static void
server_read_cb(struct bufferevent * bev,void * ctx)82*663afb9bSAndroid Build Coastguard Worker server_read_cb(struct bufferevent *bev, void *ctx)
83*663afb9bSAndroid Build Coastguard Worker {
84*663afb9bSAndroid Build Coastguard Worker 	while (evbuffer_get_length(bufferevent_get_input(bev))) {
85*663afb9bSAndroid Build Coastguard Worker 		unsigned char tmp;
86*663afb9bSAndroid Build Coastguard Worker 		bufferevent_read(bev, &tmp, 1);
87*663afb9bSAndroid Build Coastguard Worker 		bufferevent_write(bev, &tmp, 1);
88*663afb9bSAndroid Build Coastguard Worker 	}
89*663afb9bSAndroid Build Coastguard Worker }
90*663afb9bSAndroid Build Coastguard Worker 
91*663afb9bSAndroid Build Coastguard Worker /* Wait for an EOF and then free the bufferevent */
92*663afb9bSAndroid Build Coastguard Worker static void
server_event_cb(struct bufferevent * bev,short events,void * ctx)93*663afb9bSAndroid Build Coastguard Worker server_event_cb(struct bufferevent *bev, short events, void *ctx)
94*663afb9bSAndroid Build Coastguard Worker {
95*663afb9bSAndroid Build Coastguard Worker 	if (events & BEV_EVENT_ERROR) {
96*663afb9bSAndroid Build Coastguard Worker 		my_perror("Error from bufferevent");
97*663afb9bSAndroid Build Coastguard Worker 		exit(1);
98*663afb9bSAndroid Build Coastguard Worker 	} else if (events & BEV_EVENT_EOF) {
99*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(bev);
100*663afb9bSAndroid Build Coastguard Worker 		if (num_requests == MAX_REQUESTS) {
101*663afb9bSAndroid Build Coastguard Worker 			event_base_loopbreak(bufferevent_get_base(bev));
102*663afb9bSAndroid Build Coastguard Worker 		}
103*663afb9bSAndroid Build Coastguard Worker 	}
104*663afb9bSAndroid Build Coastguard Worker }
105*663afb9bSAndroid Build Coastguard Worker 
106*663afb9bSAndroid Build Coastguard Worker /* Accept a client socket and set it up to for reading & writing */
107*663afb9bSAndroid Build Coastguard Worker static void
listener_accept_cb(struct evconnlistener * listener,evutil_socket_t sock,struct sockaddr * addr,int len,void * ptr)108*663afb9bSAndroid Build Coastguard Worker listener_accept_cb(struct evconnlistener *listener, evutil_socket_t sock,
109*663afb9bSAndroid Build Coastguard Worker                    struct sockaddr *addr, int len, void *ptr)
110*663afb9bSAndroid Build Coastguard Worker {
111*663afb9bSAndroid Build Coastguard Worker 	struct event_base *base = evconnlistener_get_base(listener);
112*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *bev = bufferevent_socket_new(base, sock,
113*663afb9bSAndroid Build Coastguard Worker 		BEV_OPT_CLOSE_ON_FREE);
114*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setcb(bev, server_read_cb, NULL, server_event_cb, NULL);
115*663afb9bSAndroid Build Coastguard Worker 	bufferevent_enable(bev, EV_READ|EV_WRITE);
116*663afb9bSAndroid Build Coastguard Worker }
117*663afb9bSAndroid Build Coastguard Worker 
118*663afb9bSAndroid Build Coastguard Worker /* Start the server listening on a random port and start the first client. */
119*663afb9bSAndroid Build Coastguard Worker static void
start_loop(void)120*663afb9bSAndroid Build Coastguard Worker start_loop(void)
121*663afb9bSAndroid Build Coastguard Worker {
122*663afb9bSAndroid Build Coastguard Worker 	struct event_base *base;
123*663afb9bSAndroid Build Coastguard Worker 	struct evconnlistener *listener;
124*663afb9bSAndroid Build Coastguard Worker 	struct sockaddr_storage ss;
125*663afb9bSAndroid Build Coastguard Worker 	ev_socklen_t socklen = sizeof(ss);
126*663afb9bSAndroid Build Coastguard Worker 	evutil_socket_t fd;
127*663afb9bSAndroid Build Coastguard Worker 
128*663afb9bSAndroid Build Coastguard Worker 	base = event_base_new();
129*663afb9bSAndroid Build Coastguard Worker 	if (base == NULL) {
130*663afb9bSAndroid Build Coastguard Worker 		puts("Could not open event base!");
131*663afb9bSAndroid Build Coastguard Worker 		exit(1);
132*663afb9bSAndroid Build Coastguard Worker 	}
133*663afb9bSAndroid Build Coastguard Worker 
134*663afb9bSAndroid Build Coastguard Worker 	listener = evconnlistener_new_bind(base, listener_accept_cb, NULL,
135*663afb9bSAndroid Build Coastguard Worker 	    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
136*663afb9bSAndroid Build Coastguard Worker 	    -1, (struct sockaddr *)&saddr, sizeof(saddr));
137*663afb9bSAndroid Build Coastguard Worker 	if (listener == NULL) {
138*663afb9bSAndroid Build Coastguard Worker 		my_perror("Could not create listener!");
139*663afb9bSAndroid Build Coastguard Worker 		exit(1);
140*663afb9bSAndroid Build Coastguard Worker 	}
141*663afb9bSAndroid Build Coastguard Worker 	fd = evconnlistener_get_fd(listener);
142*663afb9bSAndroid Build Coastguard Worker 	if (fd < 0) {
143*663afb9bSAndroid Build Coastguard Worker 		puts("Couldn't get fd from listener");
144*663afb9bSAndroid Build Coastguard Worker 		exit(1);
145*663afb9bSAndroid Build Coastguard Worker 	}
146*663afb9bSAndroid Build Coastguard Worker 	if (getsockname(fd, (struct sockaddr *)&ss, &socklen) < 0) {
147*663afb9bSAndroid Build Coastguard Worker 		my_perror("getsockname()");
148*663afb9bSAndroid Build Coastguard Worker 		exit(1);
149*663afb9bSAndroid Build Coastguard Worker 	}
150*663afb9bSAndroid Build Coastguard Worker 	memcpy(&saddr, &ss, sizeof(saddr));
151*663afb9bSAndroid Build Coastguard Worker 	if (saddr.sin_family != AF_INET) {
152*663afb9bSAndroid Build Coastguard Worker 		puts("AF mismatch from getsockname().");
153*663afb9bSAndroid Build Coastguard Worker 		exit(1);
154*663afb9bSAndroid Build Coastguard Worker 	}
155*663afb9bSAndroid Build Coastguard Worker 
156*663afb9bSAndroid Build Coastguard Worker 	start_client(base);
157*663afb9bSAndroid Build Coastguard Worker 
158*663afb9bSAndroid Build Coastguard Worker 	event_base_dispatch(base);
159*663afb9bSAndroid Build Coastguard Worker 
160*663afb9bSAndroid Build Coastguard Worker 	evconnlistener_free(listener);
161*663afb9bSAndroid Build Coastguard Worker 	event_base_free(base);
162*663afb9bSAndroid Build Coastguard Worker }
163*663afb9bSAndroid Build Coastguard Worker 
164*663afb9bSAndroid Build Coastguard Worker /*
165*663afb9bSAndroid Build Coastguard Worker ===============================================
166*663afb9bSAndroid Build Coastguard Worker Client functions
167*663afb9bSAndroid Build Coastguard Worker ===============================================
168*663afb9bSAndroid Build Coastguard Worker */
169*663afb9bSAndroid Build Coastguard Worker 
170*663afb9bSAndroid Build Coastguard Worker /* Check that the server sends back the same byte that the client sent.
171*663afb9bSAndroid Build Coastguard Worker    If MAX_REQUESTS have been reached, exit. Otherwise, start another client. */
172*663afb9bSAndroid Build Coastguard Worker static void
client_read_cb(struct bufferevent * bev,void * ctx)173*663afb9bSAndroid Build Coastguard Worker client_read_cb(struct bufferevent *bev, void *ctx)
174*663afb9bSAndroid Build Coastguard Worker {
175*663afb9bSAndroid Build Coastguard Worker 	unsigned char tmp;
176*663afb9bSAndroid Build Coastguard Worker 	struct event_base *base = bufferevent_get_base(bev);
177*663afb9bSAndroid Build Coastguard Worker 
178*663afb9bSAndroid Build Coastguard Worker 	bufferevent_read(bev, &tmp, 1);
179*663afb9bSAndroid Build Coastguard Worker 	if (tmp != 'A') {
180*663afb9bSAndroid Build Coastguard Worker 		puts("Incorrect data received!");
181*663afb9bSAndroid Build Coastguard Worker 		exit(2);
182*663afb9bSAndroid Build Coastguard Worker 	}
183*663afb9bSAndroid Build Coastguard Worker 	bufferevent_free(bev);
184*663afb9bSAndroid Build Coastguard Worker 
185*663afb9bSAndroid Build Coastguard Worker 	num_requests++;
186*663afb9bSAndroid Build Coastguard Worker 	if (++num_requests < MAX_REQUESTS) {
187*663afb9bSAndroid Build Coastguard Worker 		start_client(base);
188*663afb9bSAndroid Build Coastguard Worker 	}
189*663afb9bSAndroid Build Coastguard Worker }
190*663afb9bSAndroid Build Coastguard Worker 
191*663afb9bSAndroid Build Coastguard Worker /* Send a byte to the server. */
192*663afb9bSAndroid Build Coastguard Worker static void
client_event_cb(struct bufferevent * bev,short events,void * ctx)193*663afb9bSAndroid Build Coastguard Worker client_event_cb(struct bufferevent *bev, short events, void *ctx)
194*663afb9bSAndroid Build Coastguard Worker {
195*663afb9bSAndroid Build Coastguard Worker 	if (events & BEV_EVENT_CONNECTED) {
196*663afb9bSAndroid Build Coastguard Worker 		unsigned char tmp = 'A';
197*663afb9bSAndroid Build Coastguard Worker 		bufferevent_write(bev, &tmp, 1);
198*663afb9bSAndroid Build Coastguard Worker 	} else if (events & BEV_EVENT_ERROR) {
199*663afb9bSAndroid Build Coastguard Worker 		puts("Client socket got error!");
200*663afb9bSAndroid Build Coastguard Worker 		exit(2);
201*663afb9bSAndroid Build Coastguard Worker 	}
202*663afb9bSAndroid Build Coastguard Worker 
203*663afb9bSAndroid Build Coastguard Worker 	bufferevent_enable(bev, EV_READ);
204*663afb9bSAndroid Build Coastguard Worker }
205*663afb9bSAndroid Build Coastguard Worker 
206*663afb9bSAndroid Build Coastguard Worker /* Open a client socket to connect to localhost on sin */
207*663afb9bSAndroid Build Coastguard Worker static void
start_client(struct event_base * base)208*663afb9bSAndroid Build Coastguard Worker start_client(struct event_base *base)
209*663afb9bSAndroid Build Coastguard Worker {
210*663afb9bSAndroid Build Coastguard Worker 	struct bufferevent *bev = bufferevent_socket_new(base, -1,
211*663afb9bSAndroid Build Coastguard Worker                                                          BEV_OPT_CLOSE_ON_FREE);
212*663afb9bSAndroid Build Coastguard Worker 	bufferevent_setcb(bev, client_read_cb, NULL, client_event_cb, NULL);
213*663afb9bSAndroid Build Coastguard Worker 
214*663afb9bSAndroid Build Coastguard Worker 	if (bufferevent_socket_connect(bev, (struct sockaddr *)&saddr,
215*663afb9bSAndroid Build Coastguard Worker                                        sizeof(saddr)) < 0) {
216*663afb9bSAndroid Build Coastguard Worker 		my_perror("Could not connect!");
217*663afb9bSAndroid Build Coastguard Worker 		bufferevent_free(bev);
218*663afb9bSAndroid Build Coastguard Worker 		exit(2);
219*663afb9bSAndroid Build Coastguard Worker 	}
220*663afb9bSAndroid Build Coastguard Worker }
221*663afb9bSAndroid Build Coastguard Worker 
222*663afb9bSAndroid Build Coastguard Worker int
main(int argc,char ** argv)223*663afb9bSAndroid Build Coastguard Worker main(int argc, char **argv)
224*663afb9bSAndroid Build Coastguard Worker {
225*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SETRLIMIT
226*663afb9bSAndroid Build Coastguard Worker 	/* Set the fd limit to a low value so that any fd leak is caught without
227*663afb9bSAndroid Build Coastguard Worker 	making many requests. */
228*663afb9bSAndroid Build Coastguard Worker 	struct rlimit rl;
229*663afb9bSAndroid Build Coastguard Worker 	rl.rlim_cur = rl.rlim_max = 20;
230*663afb9bSAndroid Build Coastguard Worker 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
231*663afb9bSAndroid Build Coastguard Worker 		my_perror("setrlimit");
232*663afb9bSAndroid Build Coastguard Worker 		exit(3);
233*663afb9bSAndroid Build Coastguard Worker 	}
234*663afb9bSAndroid Build Coastguard Worker #endif
235*663afb9bSAndroid Build Coastguard Worker 
236*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
237*663afb9bSAndroid Build Coastguard Worker 	WSADATA WSAData;
238*663afb9bSAndroid Build Coastguard Worker 	WSAStartup(0x101, &WSAData);
239*663afb9bSAndroid Build Coastguard Worker #endif
240*663afb9bSAndroid Build Coastguard Worker 
241*663afb9bSAndroid Build Coastguard Worker 	/* Set up an address, used by both client & server. */
242*663afb9bSAndroid Build Coastguard Worker 	memset(&saddr, 0, sizeof(saddr));
243*663afb9bSAndroid Build Coastguard Worker 	saddr.sin_family = AF_INET;
244*663afb9bSAndroid Build Coastguard Worker 	saddr.sin_addr.s_addr = htonl(0x7f000001);
245*663afb9bSAndroid Build Coastguard Worker 	saddr.sin_port = 0; /* Tell the implementation to pick a port. */
246*663afb9bSAndroid Build Coastguard Worker 
247*663afb9bSAndroid Build Coastguard Worker 	start_loop();
248*663afb9bSAndroid Build Coastguard Worker 
249*663afb9bSAndroid Build Coastguard Worker 	return 0;
250*663afb9bSAndroid Build Coastguard Worker }
251*663afb9bSAndroid Build Coastguard Worker 
252*663afb9bSAndroid Build Coastguard Worker /* XXX why does this test cause so much latency sometimes (OSX 10.5)? */
253