xref: /aosp_15_r20/external/liburing/test/connect.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * Check that IORING_OP_CONNECT works, with and without other side
4*25da2beaSAndroid Build Coastguard Worker  * being open.
5*25da2beaSAndroid Build Coastguard Worker  */
6*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
7*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
8*25da2beaSAndroid Build Coastguard Worker #include <string.h>
9*25da2beaSAndroid Build Coastguard Worker 
10*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
13*25da2beaSAndroid Build Coastguard Worker #include <poll.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/socket.h>
15*25da2beaSAndroid Build Coastguard Worker #include <netinet/in.h>
16*25da2beaSAndroid Build Coastguard Worker #include <netinet/tcp.h>
17*25da2beaSAndroid Build Coastguard Worker #include <arpa/inet.h>
18*25da2beaSAndroid Build Coastguard Worker 
19*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
20*25da2beaSAndroid Build Coastguard Worker 
21*25da2beaSAndroid Build Coastguard Worker static int no_connect;
22*25da2beaSAndroid Build Coastguard Worker static unsigned short use_port;
23*25da2beaSAndroid Build Coastguard Worker static unsigned int use_addr;
24*25da2beaSAndroid Build Coastguard Worker 
create_socket(void)25*25da2beaSAndroid Build Coastguard Worker static int create_socket(void)
26*25da2beaSAndroid Build Coastguard Worker {
27*25da2beaSAndroid Build Coastguard Worker 	int fd;
28*25da2beaSAndroid Build Coastguard Worker 
29*25da2beaSAndroid Build Coastguard Worker 	fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
30*25da2beaSAndroid Build Coastguard Worker 	if (fd == -1) {
31*25da2beaSAndroid Build Coastguard Worker 		perror("socket()");
32*25da2beaSAndroid Build Coastguard Worker 		return -1;
33*25da2beaSAndroid Build Coastguard Worker 	}
34*25da2beaSAndroid Build Coastguard Worker 
35*25da2beaSAndroid Build Coastguard Worker 	return fd;
36*25da2beaSAndroid Build Coastguard Worker }
37*25da2beaSAndroid Build Coastguard Worker 
submit_and_wait(struct io_uring * ring,int * res)38*25da2beaSAndroid Build Coastguard Worker static int submit_and_wait(struct io_uring *ring, int *res)
39*25da2beaSAndroid Build Coastguard Worker {
40*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
41*25da2beaSAndroid Build Coastguard Worker 	int ret;
42*25da2beaSAndroid Build Coastguard Worker 
43*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit_and_wait(ring, 1);
44*25da2beaSAndroid Build Coastguard Worker 	if (ret != 1) {
45*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_using_submit: got %d\n", ret);
46*25da2beaSAndroid Build Coastguard Worker 		return 1;
47*25da2beaSAndroid Build Coastguard Worker 	}
48*25da2beaSAndroid Build Coastguard Worker 
49*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_peek_cqe(ring, &cqe);
50*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
51*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_uring_peek_cqe(): no cqe returned");
52*25da2beaSAndroid Build Coastguard Worker 		return 1;
53*25da2beaSAndroid Build Coastguard Worker 	}
54*25da2beaSAndroid Build Coastguard Worker 
55*25da2beaSAndroid Build Coastguard Worker 	*res = cqe->res;
56*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(ring, cqe);
57*25da2beaSAndroid Build Coastguard Worker 	return 0;
58*25da2beaSAndroid Build Coastguard Worker }
59*25da2beaSAndroid Build Coastguard Worker 
wait_for(struct io_uring * ring,int fd,int mask)60*25da2beaSAndroid Build Coastguard Worker static int wait_for(struct io_uring *ring, int fd, int mask)
61*25da2beaSAndroid Build Coastguard Worker {
62*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
63*25da2beaSAndroid Build Coastguard Worker 	int ret, res;
64*25da2beaSAndroid Build Coastguard Worker 
65*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
66*25da2beaSAndroid Build Coastguard Worker 	if (!sqe) {
67*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to get sqe\n");
68*25da2beaSAndroid Build Coastguard Worker 		return -1;
69*25da2beaSAndroid Build Coastguard Worker 	}
70*25da2beaSAndroid Build Coastguard Worker 
71*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_poll_add(sqe, fd, mask);
72*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 2;
73*25da2beaSAndroid Build Coastguard Worker 
74*25da2beaSAndroid Build Coastguard Worker 	ret = submit_and_wait(ring, &res);
75*25da2beaSAndroid Build Coastguard Worker 	if (ret)
76*25da2beaSAndroid Build Coastguard Worker 		return -1;
77*25da2beaSAndroid Build Coastguard Worker 
78*25da2beaSAndroid Build Coastguard Worker 	if (res < 0) {
79*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "poll(): failed with %d\n", res);
80*25da2beaSAndroid Build Coastguard Worker 		return -1;
81*25da2beaSAndroid Build Coastguard Worker 	}
82*25da2beaSAndroid Build Coastguard Worker 
83*25da2beaSAndroid Build Coastguard Worker 	return res;
84*25da2beaSAndroid Build Coastguard Worker }
85*25da2beaSAndroid Build Coastguard Worker 
listen_on_socket(int fd)86*25da2beaSAndroid Build Coastguard Worker static int listen_on_socket(int fd)
87*25da2beaSAndroid Build Coastguard Worker {
88*25da2beaSAndroid Build Coastguard Worker 	struct sockaddr_in addr;
89*25da2beaSAndroid Build Coastguard Worker 	int ret;
90*25da2beaSAndroid Build Coastguard Worker 
91*25da2beaSAndroid Build Coastguard Worker 	memset(&addr, 0, sizeof(addr));
92*25da2beaSAndroid Build Coastguard Worker 	addr.sin_family = AF_INET;
93*25da2beaSAndroid Build Coastguard Worker 	addr.sin_port = use_port;
94*25da2beaSAndroid Build Coastguard Worker 	addr.sin_addr.s_addr = use_addr;
95*25da2beaSAndroid Build Coastguard Worker 
96*25da2beaSAndroid Build Coastguard Worker 	ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
97*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
98*25da2beaSAndroid Build Coastguard Worker 		perror("bind()");
99*25da2beaSAndroid Build Coastguard Worker 		return -1;
100*25da2beaSAndroid Build Coastguard Worker 	}
101*25da2beaSAndroid Build Coastguard Worker 
102*25da2beaSAndroid Build Coastguard Worker 	ret = listen(fd, 128);
103*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
104*25da2beaSAndroid Build Coastguard Worker 		perror("listen()");
105*25da2beaSAndroid Build Coastguard Worker 		return -1;
106*25da2beaSAndroid Build Coastguard Worker 	}
107*25da2beaSAndroid Build Coastguard Worker 
108*25da2beaSAndroid Build Coastguard Worker 	return 0;
109*25da2beaSAndroid Build Coastguard Worker }
110*25da2beaSAndroid Build Coastguard Worker 
configure_connect(int fd,struct sockaddr_in * addr)111*25da2beaSAndroid Build Coastguard Worker static int configure_connect(int fd, struct sockaddr_in* addr)
112*25da2beaSAndroid Build Coastguard Worker {
113*25da2beaSAndroid Build Coastguard Worker 	int ret, val = 1;
114*25da2beaSAndroid Build Coastguard Worker 
115*25da2beaSAndroid Build Coastguard Worker 	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
116*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
117*25da2beaSAndroid Build Coastguard Worker 		perror("setsockopt()");
118*25da2beaSAndroid Build Coastguard Worker 		return -1;
119*25da2beaSAndroid Build Coastguard Worker 	}
120*25da2beaSAndroid Build Coastguard Worker 
121*25da2beaSAndroid Build Coastguard Worker 	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
122*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
123*25da2beaSAndroid Build Coastguard Worker 		perror("setsockopt()");
124*25da2beaSAndroid Build Coastguard Worker 		return -1;
125*25da2beaSAndroid Build Coastguard Worker 	}
126*25da2beaSAndroid Build Coastguard Worker 
127*25da2beaSAndroid Build Coastguard Worker 	memset(addr, 0, sizeof(*addr));
128*25da2beaSAndroid Build Coastguard Worker 	addr->sin_family = AF_INET;
129*25da2beaSAndroid Build Coastguard Worker 	addr->sin_port = use_port;
130*25da2beaSAndroid Build Coastguard Worker 	ret = inet_aton("127.0.0.1", &addr->sin_addr);
131*25da2beaSAndroid Build Coastguard Worker 	return ret;
132*25da2beaSAndroid Build Coastguard Worker }
133*25da2beaSAndroid Build Coastguard Worker 
connect_socket(struct io_uring * ring,int fd,int * code)134*25da2beaSAndroid Build Coastguard Worker static int connect_socket(struct io_uring *ring, int fd, int *code)
135*25da2beaSAndroid Build Coastguard Worker {
136*25da2beaSAndroid Build Coastguard Worker 	struct sockaddr_in addr;
137*25da2beaSAndroid Build Coastguard Worker 	int ret, res;
138*25da2beaSAndroid Build Coastguard Worker 	socklen_t code_len = sizeof(*code);
139*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
140*25da2beaSAndroid Build Coastguard Worker 
141*25da2beaSAndroid Build Coastguard Worker 	if (configure_connect(fd, &addr) == -1)
142*25da2beaSAndroid Build Coastguard Worker 		return -1;
143*25da2beaSAndroid Build Coastguard Worker 
144*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
145*25da2beaSAndroid Build Coastguard Worker 	if (!sqe) {
146*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to get sqe\n");
147*25da2beaSAndroid Build Coastguard Worker 		return -1;
148*25da2beaSAndroid Build Coastguard Worker 	}
149*25da2beaSAndroid Build Coastguard Worker 
150*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_connect(sqe, fd, (struct sockaddr*)&addr, sizeof(addr));
151*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 1;
152*25da2beaSAndroid Build Coastguard Worker 
153*25da2beaSAndroid Build Coastguard Worker 	ret = submit_and_wait(ring, &res);
154*25da2beaSAndroid Build Coastguard Worker 	if (ret)
155*25da2beaSAndroid Build Coastguard Worker 		return -1;
156*25da2beaSAndroid Build Coastguard Worker 
157*25da2beaSAndroid Build Coastguard Worker 	if (res == -EINPROGRESS) {
158*25da2beaSAndroid Build Coastguard Worker 		ret = wait_for(ring, fd, POLLOUT | POLLHUP | POLLERR);
159*25da2beaSAndroid Build Coastguard Worker 		if (ret == -1)
160*25da2beaSAndroid Build Coastguard Worker 			return -1;
161*25da2beaSAndroid Build Coastguard Worker 
162*25da2beaSAndroid Build Coastguard Worker 		int ev = (ret & POLLOUT) || (ret & POLLHUP) || (ret & POLLERR);
163*25da2beaSAndroid Build Coastguard Worker 		if (!ev) {
164*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "poll(): returned invalid value %#x\n", ret);
165*25da2beaSAndroid Build Coastguard Worker 			return -1;
166*25da2beaSAndroid Build Coastguard Worker 		}
167*25da2beaSAndroid Build Coastguard Worker 
168*25da2beaSAndroid Build Coastguard Worker 		ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, code, &code_len);
169*25da2beaSAndroid Build Coastguard Worker 		if (ret == -1) {
170*25da2beaSAndroid Build Coastguard Worker 			perror("getsockopt()");
171*25da2beaSAndroid Build Coastguard Worker 			return -1;
172*25da2beaSAndroid Build Coastguard Worker 		}
173*25da2beaSAndroid Build Coastguard Worker 	} else
174*25da2beaSAndroid Build Coastguard Worker 		*code = res;
175*25da2beaSAndroid Build Coastguard Worker 	return 0;
176*25da2beaSAndroid Build Coastguard Worker }
177*25da2beaSAndroid Build Coastguard Worker 
test_connect_with_no_peer(struct io_uring * ring)178*25da2beaSAndroid Build Coastguard Worker static int test_connect_with_no_peer(struct io_uring *ring)
179*25da2beaSAndroid Build Coastguard Worker {
180*25da2beaSAndroid Build Coastguard Worker 	int connect_fd;
181*25da2beaSAndroid Build Coastguard Worker 	int ret, code;
182*25da2beaSAndroid Build Coastguard Worker 
183*25da2beaSAndroid Build Coastguard Worker 	connect_fd = create_socket();
184*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd == -1)
185*25da2beaSAndroid Build Coastguard Worker 		return -1;
186*25da2beaSAndroid Build Coastguard Worker 
187*25da2beaSAndroid Build Coastguard Worker 	ret = connect_socket(ring, connect_fd, &code);
188*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1)
189*25da2beaSAndroid Build Coastguard Worker 		goto err;
190*25da2beaSAndroid Build Coastguard Worker 
191*25da2beaSAndroid Build Coastguard Worker 	if (code != -ECONNREFUSED) {
192*25da2beaSAndroid Build Coastguard Worker 		if (code == -EINVAL || code == -EBADF || code == -EOPNOTSUPP) {
193*25da2beaSAndroid Build Coastguard Worker 			fprintf(stdout, "No connect support, skipping\n");
194*25da2beaSAndroid Build Coastguard Worker 			no_connect = 1;
195*25da2beaSAndroid Build Coastguard Worker 			goto out;
196*25da2beaSAndroid Build Coastguard Worker 		}
197*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "connect failed with %d\n", code);
198*25da2beaSAndroid Build Coastguard Worker 		goto err;
199*25da2beaSAndroid Build Coastguard Worker 	}
200*25da2beaSAndroid Build Coastguard Worker 
201*25da2beaSAndroid Build Coastguard Worker out:
202*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd);
203*25da2beaSAndroid Build Coastguard Worker 	return 0;
204*25da2beaSAndroid Build Coastguard Worker 
205*25da2beaSAndroid Build Coastguard Worker err:
206*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd);
207*25da2beaSAndroid Build Coastguard Worker 	return -1;
208*25da2beaSAndroid Build Coastguard Worker }
209*25da2beaSAndroid Build Coastguard Worker 
test_connect(struct io_uring * ring)210*25da2beaSAndroid Build Coastguard Worker static int test_connect(struct io_uring *ring)
211*25da2beaSAndroid Build Coastguard Worker {
212*25da2beaSAndroid Build Coastguard Worker 	int accept_fd;
213*25da2beaSAndroid Build Coastguard Worker 	int connect_fd;
214*25da2beaSAndroid Build Coastguard Worker 	int ret, code;
215*25da2beaSAndroid Build Coastguard Worker 
216*25da2beaSAndroid Build Coastguard Worker 	accept_fd = create_socket();
217*25da2beaSAndroid Build Coastguard Worker 	if (accept_fd == -1)
218*25da2beaSAndroid Build Coastguard Worker 		return -1;
219*25da2beaSAndroid Build Coastguard Worker 
220*25da2beaSAndroid Build Coastguard Worker 	ret = listen_on_socket(accept_fd);
221*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1)
222*25da2beaSAndroid Build Coastguard Worker 		goto err1;
223*25da2beaSAndroid Build Coastguard Worker 
224*25da2beaSAndroid Build Coastguard Worker 	connect_fd = create_socket();
225*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd == -1)
226*25da2beaSAndroid Build Coastguard Worker 		goto err1;
227*25da2beaSAndroid Build Coastguard Worker 
228*25da2beaSAndroid Build Coastguard Worker 	ret = connect_socket(ring, connect_fd, &code);
229*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1)
230*25da2beaSAndroid Build Coastguard Worker 		goto err2;
231*25da2beaSAndroid Build Coastguard Worker 
232*25da2beaSAndroid Build Coastguard Worker 	if (code != 0) {
233*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "connect failed with %d\n", code);
234*25da2beaSAndroid Build Coastguard Worker 		goto err2;
235*25da2beaSAndroid Build Coastguard Worker 	}
236*25da2beaSAndroid Build Coastguard Worker 
237*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd);
238*25da2beaSAndroid Build Coastguard Worker 	close(accept_fd);
239*25da2beaSAndroid Build Coastguard Worker 
240*25da2beaSAndroid Build Coastguard Worker 	return 0;
241*25da2beaSAndroid Build Coastguard Worker 
242*25da2beaSAndroid Build Coastguard Worker err2:
243*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd);
244*25da2beaSAndroid Build Coastguard Worker 
245*25da2beaSAndroid Build Coastguard Worker err1:
246*25da2beaSAndroid Build Coastguard Worker 	close(accept_fd);
247*25da2beaSAndroid Build Coastguard Worker 	return -1;
248*25da2beaSAndroid Build Coastguard Worker }
249*25da2beaSAndroid Build Coastguard Worker 
test_connect_timeout(struct io_uring * ring)250*25da2beaSAndroid Build Coastguard Worker static int test_connect_timeout(struct io_uring *ring)
251*25da2beaSAndroid Build Coastguard Worker {
252*25da2beaSAndroid Build Coastguard Worker 	int connect_fd[2] = {-1, -1};
253*25da2beaSAndroid Build Coastguard Worker 	int accept_fd = -1;
254*25da2beaSAndroid Build Coastguard Worker 	int ret, code;
255*25da2beaSAndroid Build Coastguard Worker 	struct sockaddr_in addr;
256*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
257*25da2beaSAndroid Build Coastguard Worker 	struct __kernel_timespec ts = {.tv_sec = 0, .tv_nsec = 100000};
258*25da2beaSAndroid Build Coastguard Worker 
259*25da2beaSAndroid Build Coastguard Worker 	connect_fd[0] = create_socket();
260*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd[0] == -1)
261*25da2beaSAndroid Build Coastguard Worker 		return -1;
262*25da2beaSAndroid Build Coastguard Worker 
263*25da2beaSAndroid Build Coastguard Worker 	connect_fd[1] = create_socket();
264*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd[1] == -1)
265*25da2beaSAndroid Build Coastguard Worker 		goto err;
266*25da2beaSAndroid Build Coastguard Worker 
267*25da2beaSAndroid Build Coastguard Worker 	accept_fd = create_socket();
268*25da2beaSAndroid Build Coastguard Worker 	if (accept_fd == -1)
269*25da2beaSAndroid Build Coastguard Worker 		goto err;
270*25da2beaSAndroid Build Coastguard Worker 
271*25da2beaSAndroid Build Coastguard Worker 	if (configure_connect(connect_fd[0], &addr) == -1)
272*25da2beaSAndroid Build Coastguard Worker 		goto err;
273*25da2beaSAndroid Build Coastguard Worker 
274*25da2beaSAndroid Build Coastguard Worker 	if (configure_connect(connect_fd[1], &addr) == -1)
275*25da2beaSAndroid Build Coastguard Worker 		goto err;
276*25da2beaSAndroid Build Coastguard Worker 
277*25da2beaSAndroid Build Coastguard Worker 	ret = bind(accept_fd, (struct sockaddr*)&addr, sizeof(addr));
278*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
279*25da2beaSAndroid Build Coastguard Worker 		perror("bind()");
280*25da2beaSAndroid Build Coastguard Worker 		goto err;
281*25da2beaSAndroid Build Coastguard Worker 	}
282*25da2beaSAndroid Build Coastguard Worker 
283*25da2beaSAndroid Build Coastguard Worker 	ret = listen(accept_fd, 0);  // no backlog in order to block connect_fd[1]
284*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
285*25da2beaSAndroid Build Coastguard Worker 		perror("listen()");
286*25da2beaSAndroid Build Coastguard Worker 		goto err;
287*25da2beaSAndroid Build Coastguard Worker 	}
288*25da2beaSAndroid Build Coastguard Worker 
289*25da2beaSAndroid Build Coastguard Worker 	// We first connect with one client socket in order to fill the accept queue.
290*25da2beaSAndroid Build Coastguard Worker 	ret = connect_socket(ring, connect_fd[0], &code);
291*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1 || code != 0) {
292*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to connect\n");
293*25da2beaSAndroid Build Coastguard Worker 		goto err;
294*25da2beaSAndroid Build Coastguard Worker 	}
295*25da2beaSAndroid Build Coastguard Worker 
296*25da2beaSAndroid Build Coastguard Worker 	// We do not offload completion events from listening socket on purpose.
297*25da2beaSAndroid Build Coastguard Worker 	// This way we create a state where the second connect request being stalled by OS.
298*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
299*25da2beaSAndroid Build Coastguard Worker 	if (!sqe) {
300*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to get sqe\n");
301*25da2beaSAndroid Build Coastguard Worker 		goto err;
302*25da2beaSAndroid Build Coastguard Worker 	}
303*25da2beaSAndroid Build Coastguard Worker 
304*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_connect(sqe, connect_fd[1], (struct sockaddr*)&addr, sizeof(addr));
305*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 1;
306*25da2beaSAndroid Build Coastguard Worker 	sqe->flags |= IOSQE_IO_LINK;
307*25da2beaSAndroid Build Coastguard Worker 
308*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
309*25da2beaSAndroid Build Coastguard Worker 	if (!sqe) {
310*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "unable to get sqe\n");
311*25da2beaSAndroid Build Coastguard Worker 		goto err;
312*25da2beaSAndroid Build Coastguard Worker 	}
313*25da2beaSAndroid Build Coastguard Worker 	io_uring_prep_link_timeout(sqe, &ts, 0);
314*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 2;
315*25da2beaSAndroid Build Coastguard Worker 
316*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
317*25da2beaSAndroid Build Coastguard Worker 	if (ret != 2) {
318*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submitted %d\n", ret);
319*25da2beaSAndroid Build Coastguard Worker 		return -1;
320*25da2beaSAndroid Build Coastguard Worker 	}
321*25da2beaSAndroid Build Coastguard Worker 
322*25da2beaSAndroid Build Coastguard Worker 	for (int i = 0; i < 2; i++) {
323*25da2beaSAndroid Build Coastguard Worker 		int expected;
324*25da2beaSAndroid Build Coastguard Worker 		struct io_uring_cqe *cqe;
325*25da2beaSAndroid Build Coastguard Worker 
326*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(ring, &cqe);
327*25da2beaSAndroid Build Coastguard Worker 		if (ret) {
328*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "wait_cqe=%d\n", ret);
329*25da2beaSAndroid Build Coastguard Worker 			return -1;
330*25da2beaSAndroid Build Coastguard Worker 		}
331*25da2beaSAndroid Build Coastguard Worker 
332*25da2beaSAndroid Build Coastguard Worker 		expected = (cqe->user_data == 1) ? -ECANCELED : -ETIME;
333*25da2beaSAndroid Build Coastguard Worker 		if (expected != cqe->res) {
334*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "cqe %d, res %d, wanted %d\n",
335*25da2beaSAndroid Build Coastguard Worker 					(int)cqe->user_data, cqe->res, expected);
336*25da2beaSAndroid Build Coastguard Worker 			goto err;
337*25da2beaSAndroid Build Coastguard Worker 		}
338*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(ring, cqe);
339*25da2beaSAndroid Build Coastguard Worker 	}
340*25da2beaSAndroid Build Coastguard Worker 
341*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd[0]);
342*25da2beaSAndroid Build Coastguard Worker 	close(connect_fd[1]);
343*25da2beaSAndroid Build Coastguard Worker 	close(accept_fd);
344*25da2beaSAndroid Build Coastguard Worker 	return 0;
345*25da2beaSAndroid Build Coastguard Worker 
346*25da2beaSAndroid Build Coastguard Worker err:
347*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd[0] != -1)
348*25da2beaSAndroid Build Coastguard Worker 		close(connect_fd[0]);
349*25da2beaSAndroid Build Coastguard Worker 	if (connect_fd[1] != -1)
350*25da2beaSAndroid Build Coastguard Worker 		close(connect_fd[1]);
351*25da2beaSAndroid Build Coastguard Worker 
352*25da2beaSAndroid Build Coastguard Worker 	if (accept_fd != -1)
353*25da2beaSAndroid Build Coastguard Worker 		close(accept_fd);
354*25da2beaSAndroid Build Coastguard Worker 	return -1;
355*25da2beaSAndroid Build Coastguard Worker }
356*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char * argv[])357*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
358*25da2beaSAndroid Build Coastguard Worker {
359*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
360*25da2beaSAndroid Build Coastguard Worker 	int ret;
361*25da2beaSAndroid Build Coastguard Worker 
362*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1)
363*25da2beaSAndroid Build Coastguard Worker 		return 0;
364*25da2beaSAndroid Build Coastguard Worker 
365*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(8, &ring, 0);
366*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
367*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "io_uring_queue_setup() = %d\n", ret);
368*25da2beaSAndroid Build Coastguard Worker 		return 1;
369*25da2beaSAndroid Build Coastguard Worker 	}
370*25da2beaSAndroid Build Coastguard Worker 
371*25da2beaSAndroid Build Coastguard Worker 	srand(getpid());
372*25da2beaSAndroid Build Coastguard Worker 	use_port = (rand() % 61440) + 4096;
373*25da2beaSAndroid Build Coastguard Worker 	use_port = htons(use_port);
374*25da2beaSAndroid Build Coastguard Worker 	use_addr = inet_addr("127.0.0.1");
375*25da2beaSAndroid Build Coastguard Worker 
376*25da2beaSAndroid Build Coastguard Worker 	ret = test_connect_with_no_peer(&ring);
377*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
378*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_connect_with_no_peer(): failed\n");
379*25da2beaSAndroid Build Coastguard Worker 		return 1;
380*25da2beaSAndroid Build Coastguard Worker 	}
381*25da2beaSAndroid Build Coastguard Worker 	if (no_connect)
382*25da2beaSAndroid Build Coastguard Worker 		return 0;
383*25da2beaSAndroid Build Coastguard Worker 
384*25da2beaSAndroid Build Coastguard Worker 	ret = test_connect(&ring);
385*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
386*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_connect(): failed\n");
387*25da2beaSAndroid Build Coastguard Worker 		return 1;
388*25da2beaSAndroid Build Coastguard Worker 	}
389*25da2beaSAndroid Build Coastguard Worker 
390*25da2beaSAndroid Build Coastguard Worker 	ret = test_connect_timeout(&ring);
391*25da2beaSAndroid Build Coastguard Worker 	if (ret == -1) {
392*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test_connect_timeout(): failed\n");
393*25da2beaSAndroid Build Coastguard Worker 		return 1;
394*25da2beaSAndroid Build Coastguard Worker 	}
395*25da2beaSAndroid Build Coastguard Worker 
396*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
397*25da2beaSAndroid Build Coastguard Worker 	return 0;
398*25da2beaSAndroid Build Coastguard Worker }
399