xref: /aosp_15_r20/external/liburing/test/recv-msgall-stream.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1*25da2beaSAndroid Build Coastguard Worker /* SPDX-License-Identifier: MIT */
2*25da2beaSAndroid Build Coastguard Worker /*
3*25da2beaSAndroid Build Coastguard Worker  * Test MSG_WAITALL for recv/recvmsg and include normal sync versions just
4*25da2beaSAndroid Build Coastguard Worker  * for comparison.
5*25da2beaSAndroid Build Coastguard Worker  */
6*25da2beaSAndroid Build Coastguard Worker #include <errno.h>
7*25da2beaSAndroid Build Coastguard Worker #include <stdio.h>
8*25da2beaSAndroid Build Coastguard Worker #include <stdlib.h>
9*25da2beaSAndroid Build Coastguard Worker #include <string.h>
10*25da2beaSAndroid Build Coastguard Worker #include <unistd.h>
11*25da2beaSAndroid Build Coastguard Worker #include <fcntl.h>
12*25da2beaSAndroid Build Coastguard Worker #include <arpa/inet.h>
13*25da2beaSAndroid Build Coastguard Worker #include <sys/types.h>
14*25da2beaSAndroid Build Coastguard Worker #include <sys/socket.h>
15*25da2beaSAndroid Build Coastguard Worker #include <pthread.h>
16*25da2beaSAndroid Build Coastguard Worker 
17*25da2beaSAndroid Build Coastguard Worker #include "liburing.h"
18*25da2beaSAndroid Build Coastguard Worker #include "helpers.h"
19*25da2beaSAndroid Build Coastguard Worker 
20*25da2beaSAndroid Build Coastguard Worker #define MAX_MSG	128
21*25da2beaSAndroid Build Coastguard Worker 
22*25da2beaSAndroid Build Coastguard Worker static int port = 31200;
23*25da2beaSAndroid Build Coastguard Worker 
24*25da2beaSAndroid Build Coastguard Worker struct recv_data {
25*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_t mutex;
26*25da2beaSAndroid Build Coastguard Worker 	int use_recvmsg;
27*25da2beaSAndroid Build Coastguard Worker 	int use_sync;
28*25da2beaSAndroid Build Coastguard Worker 	int port;
29*25da2beaSAndroid Build Coastguard Worker };
30*25da2beaSAndroid Build Coastguard Worker 
get_conn_sock(struct recv_data * rd,int * sockout)31*25da2beaSAndroid Build Coastguard Worker static int get_conn_sock(struct recv_data *rd, int *sockout)
32*25da2beaSAndroid Build Coastguard Worker {
33*25da2beaSAndroid Build Coastguard Worker 	struct sockaddr_in saddr;
34*25da2beaSAndroid Build Coastguard Worker 	int sockfd, ret, val;
35*25da2beaSAndroid Build Coastguard Worker 
36*25da2beaSAndroid Build Coastguard Worker 	memset(&saddr, 0, sizeof(saddr));
37*25da2beaSAndroid Build Coastguard Worker 	saddr.sin_family = AF_INET;
38*25da2beaSAndroid Build Coastguard Worker 	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
39*25da2beaSAndroid Build Coastguard Worker 	saddr.sin_port = htons(rd->port);
40*25da2beaSAndroid Build Coastguard Worker 
41*25da2beaSAndroid Build Coastguard Worker 	sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
42*25da2beaSAndroid Build Coastguard Worker 	if (sockfd < 0) {
43*25da2beaSAndroid Build Coastguard Worker 		perror("socket");
44*25da2beaSAndroid Build Coastguard Worker 		goto err;
45*25da2beaSAndroid Build Coastguard Worker 	}
46*25da2beaSAndroid Build Coastguard Worker 
47*25da2beaSAndroid Build Coastguard Worker 	val = 1;
48*25da2beaSAndroid Build Coastguard Worker 	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
49*25da2beaSAndroid Build Coastguard Worker 	setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
50*25da2beaSAndroid Build Coastguard Worker 
51*25da2beaSAndroid Build Coastguard Worker 	ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
52*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
53*25da2beaSAndroid Build Coastguard Worker 		perror("bind");
54*25da2beaSAndroid Build Coastguard Worker 		goto err;
55*25da2beaSAndroid Build Coastguard Worker 	}
56*25da2beaSAndroid Build Coastguard Worker 
57*25da2beaSAndroid Build Coastguard Worker 	ret = listen(sockfd, 16);
58*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
59*25da2beaSAndroid Build Coastguard Worker 		perror("listen");
60*25da2beaSAndroid Build Coastguard Worker 		goto err;
61*25da2beaSAndroid Build Coastguard Worker 	}
62*25da2beaSAndroid Build Coastguard Worker 
63*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_unlock(&rd->mutex);
64*25da2beaSAndroid Build Coastguard Worker 
65*25da2beaSAndroid Build Coastguard Worker 	ret = accept(sockfd, NULL, NULL);
66*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
67*25da2beaSAndroid Build Coastguard Worker 		perror("accept");
68*25da2beaSAndroid Build Coastguard Worker 		return -1;
69*25da2beaSAndroid Build Coastguard Worker 	}
70*25da2beaSAndroid Build Coastguard Worker 
71*25da2beaSAndroid Build Coastguard Worker 	*sockout = sockfd;
72*25da2beaSAndroid Build Coastguard Worker 	return ret;
73*25da2beaSAndroid Build Coastguard Worker err:
74*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_unlock(&rd->mutex);
75*25da2beaSAndroid Build Coastguard Worker 	return -1;
76*25da2beaSAndroid Build Coastguard Worker }
77*25da2beaSAndroid Build Coastguard Worker 
recv_prep(struct io_uring * ring,struct iovec * iov,int * sock,struct recv_data * rd)78*25da2beaSAndroid Build Coastguard Worker static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock,
79*25da2beaSAndroid Build Coastguard Worker 		     struct recv_data *rd)
80*25da2beaSAndroid Build Coastguard Worker {
81*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
82*25da2beaSAndroid Build Coastguard Worker 	struct msghdr msg = { };
83*25da2beaSAndroid Build Coastguard Worker 	int sockfd, sockout = -1, ret;
84*25da2beaSAndroid Build Coastguard Worker 
85*25da2beaSAndroid Build Coastguard Worker 	sockfd = get_conn_sock(rd, &sockout);
86*25da2beaSAndroid Build Coastguard Worker 	if (sockfd < 0)
87*25da2beaSAndroid Build Coastguard Worker 		goto err;
88*25da2beaSAndroid Build Coastguard Worker 
89*25da2beaSAndroid Build Coastguard Worker 	sqe = io_uring_get_sqe(ring);
90*25da2beaSAndroid Build Coastguard Worker 	if (!rd->use_recvmsg) {
91*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len,
92*25da2beaSAndroid Build Coastguard Worker 					MSG_WAITALL);
93*25da2beaSAndroid Build Coastguard Worker 	} else {
94*25da2beaSAndroid Build Coastguard Worker 		msg.msg_namelen = sizeof(struct sockaddr_in);
95*25da2beaSAndroid Build Coastguard Worker 		msg.msg_iov = iov;
96*25da2beaSAndroid Build Coastguard Worker 		msg.msg_iovlen = 1;
97*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_recvmsg(sqe, sockfd, &msg, MSG_WAITALL);
98*25da2beaSAndroid Build Coastguard Worker 	}
99*25da2beaSAndroid Build Coastguard Worker 
100*25da2beaSAndroid Build Coastguard Worker 	sqe->user_data = 2;
101*25da2beaSAndroid Build Coastguard Worker 
102*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_submit(ring);
103*25da2beaSAndroid Build Coastguard Worker 	if (ret <= 0) {
104*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "submit failed: %d\n", ret);
105*25da2beaSAndroid Build Coastguard Worker 		goto err;
106*25da2beaSAndroid Build Coastguard Worker 	}
107*25da2beaSAndroid Build Coastguard Worker 
108*25da2beaSAndroid Build Coastguard Worker 	*sock = sockfd;
109*25da2beaSAndroid Build Coastguard Worker 	return 0;
110*25da2beaSAndroid Build Coastguard Worker err:
111*25da2beaSAndroid Build Coastguard Worker 	if (sockout != -1) {
112*25da2beaSAndroid Build Coastguard Worker 		shutdown(sockout, SHUT_RDWR);
113*25da2beaSAndroid Build Coastguard Worker 		close(sockout);
114*25da2beaSAndroid Build Coastguard Worker 	}
115*25da2beaSAndroid Build Coastguard Worker 	if (sockfd != -1) {
116*25da2beaSAndroid Build Coastguard Worker 		shutdown(sockfd, SHUT_RDWR);
117*25da2beaSAndroid Build Coastguard Worker 		close(sockfd);
118*25da2beaSAndroid Build Coastguard Worker 	}
119*25da2beaSAndroid Build Coastguard Worker 	return 1;
120*25da2beaSAndroid Build Coastguard Worker }
121*25da2beaSAndroid Build Coastguard Worker 
do_recv(struct io_uring * ring)122*25da2beaSAndroid Build Coastguard Worker static int do_recv(struct io_uring *ring)
123*25da2beaSAndroid Build Coastguard Worker {
124*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
125*25da2beaSAndroid Build Coastguard Worker 	int ret;
126*25da2beaSAndroid Build Coastguard Worker 
127*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_wait_cqe(ring, &cqe);
128*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
129*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "wait_cqe: %d\n", ret);
130*25da2beaSAndroid Build Coastguard Worker 		goto err;
131*25da2beaSAndroid Build Coastguard Worker 	}
132*25da2beaSAndroid Build Coastguard Worker 	if (cqe->res == -EINVAL) {
133*25da2beaSAndroid Build Coastguard Worker 		fprintf(stdout, "recv not supported, skipping\n");
134*25da2beaSAndroid Build Coastguard Worker 		return 0;
135*25da2beaSAndroid Build Coastguard Worker 	}
136*25da2beaSAndroid Build Coastguard Worker 	if (cqe->res < 0) {
137*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "failed cqe: %d\n", cqe->res);
138*25da2beaSAndroid Build Coastguard Worker 		goto err;
139*25da2beaSAndroid Build Coastguard Worker 	}
140*25da2beaSAndroid Build Coastguard Worker 	if (cqe->res != MAX_MSG * sizeof(int)) {
141*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "got wrong length: %d\n", cqe->res);
142*25da2beaSAndroid Build Coastguard Worker 		goto err;
143*25da2beaSAndroid Build Coastguard Worker 	}
144*25da2beaSAndroid Build Coastguard Worker 
145*25da2beaSAndroid Build Coastguard Worker 	io_uring_cqe_seen(ring, cqe);
146*25da2beaSAndroid Build Coastguard Worker 	return 0;
147*25da2beaSAndroid Build Coastguard Worker err:
148*25da2beaSAndroid Build Coastguard Worker 	return 1;
149*25da2beaSAndroid Build Coastguard Worker }
150*25da2beaSAndroid Build Coastguard Worker 
recv_sync(struct recv_data * rd)151*25da2beaSAndroid Build Coastguard Worker static int recv_sync(struct recv_data *rd)
152*25da2beaSAndroid Build Coastguard Worker {
153*25da2beaSAndroid Build Coastguard Worker 	int buf[MAX_MSG];
154*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov = {
155*25da2beaSAndroid Build Coastguard Worker 		.iov_base = buf,
156*25da2beaSAndroid Build Coastguard Worker 		.iov_len = sizeof(buf),
157*25da2beaSAndroid Build Coastguard Worker 	};
158*25da2beaSAndroid Build Coastguard Worker 	int i, ret, sockfd, sockout = -1;
159*25da2beaSAndroid Build Coastguard Worker 
160*25da2beaSAndroid Build Coastguard Worker 	sockfd = get_conn_sock(rd, &sockout);
161*25da2beaSAndroid Build Coastguard Worker 
162*25da2beaSAndroid Build Coastguard Worker 	if (rd->use_recvmsg) {
163*25da2beaSAndroid Build Coastguard Worker 		struct msghdr msg = { };
164*25da2beaSAndroid Build Coastguard Worker 
165*25da2beaSAndroid Build Coastguard Worker 		msg.msg_namelen = sizeof(struct sockaddr_in);
166*25da2beaSAndroid Build Coastguard Worker 		msg.msg_iov = &iov;
167*25da2beaSAndroid Build Coastguard Worker 		msg.msg_iovlen = 1;
168*25da2beaSAndroid Build Coastguard Worker 		ret = recvmsg(sockfd, &msg, MSG_WAITALL);
169*25da2beaSAndroid Build Coastguard Worker 	} else {
170*25da2beaSAndroid Build Coastguard Worker 		ret = recv(sockfd, buf, sizeof(buf), MSG_WAITALL);
171*25da2beaSAndroid Build Coastguard Worker 	}
172*25da2beaSAndroid Build Coastguard Worker 
173*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
174*25da2beaSAndroid Build Coastguard Worker 		perror("receive");
175*25da2beaSAndroid Build Coastguard Worker 		goto err;
176*25da2beaSAndroid Build Coastguard Worker 	}
177*25da2beaSAndroid Build Coastguard Worker 
178*25da2beaSAndroid Build Coastguard Worker 	if (ret != sizeof(buf)) {
179*25da2beaSAndroid Build Coastguard Worker 		ret = -1;
180*25da2beaSAndroid Build Coastguard Worker 		goto err;
181*25da2beaSAndroid Build Coastguard Worker 	}
182*25da2beaSAndroid Build Coastguard Worker 
183*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < MAX_MSG; i++) {
184*25da2beaSAndroid Build Coastguard Worker 		if (buf[i] != i)
185*25da2beaSAndroid Build Coastguard Worker 			goto err;
186*25da2beaSAndroid Build Coastguard Worker 	}
187*25da2beaSAndroid Build Coastguard Worker 	ret = 0;
188*25da2beaSAndroid Build Coastguard Worker err:
189*25da2beaSAndroid Build Coastguard Worker 	shutdown(sockout, SHUT_RDWR);
190*25da2beaSAndroid Build Coastguard Worker 	shutdown(sockfd, SHUT_RDWR);
191*25da2beaSAndroid Build Coastguard Worker 	close(sockout);
192*25da2beaSAndroid Build Coastguard Worker 	close(sockfd);
193*25da2beaSAndroid Build Coastguard Worker 	return ret;
194*25da2beaSAndroid Build Coastguard Worker }
195*25da2beaSAndroid Build Coastguard Worker 
recv_uring(struct recv_data * rd)196*25da2beaSAndroid Build Coastguard Worker static int recv_uring(struct recv_data *rd)
197*25da2beaSAndroid Build Coastguard Worker {
198*25da2beaSAndroid Build Coastguard Worker 	int buf[MAX_MSG];
199*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov = {
200*25da2beaSAndroid Build Coastguard Worker 		.iov_base = buf,
201*25da2beaSAndroid Build Coastguard Worker 		.iov_len = sizeof(buf),
202*25da2beaSAndroid Build Coastguard Worker 	};
203*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_params p = { };
204*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
205*25da2beaSAndroid Build Coastguard Worker 	int ret, sock = -1, sockout = -1;
206*25da2beaSAndroid Build Coastguard Worker 
207*25da2beaSAndroid Build Coastguard Worker 	ret = t_create_ring_params(1, &ring, &p);
208*25da2beaSAndroid Build Coastguard Worker 	if (ret == T_SETUP_SKIP) {
209*25da2beaSAndroid Build Coastguard Worker 		pthread_mutex_unlock(&rd->mutex);
210*25da2beaSAndroid Build Coastguard Worker 		ret = 0;
211*25da2beaSAndroid Build Coastguard Worker 		goto err;
212*25da2beaSAndroid Build Coastguard Worker 	} else if (ret < 0) {
213*25da2beaSAndroid Build Coastguard Worker 		pthread_mutex_unlock(&rd->mutex);
214*25da2beaSAndroid Build Coastguard Worker 		goto err;
215*25da2beaSAndroid Build Coastguard Worker 	}
216*25da2beaSAndroid Build Coastguard Worker 
217*25da2beaSAndroid Build Coastguard Worker 	sock = recv_prep(&ring, &iov, &sockout, rd);
218*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
219*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "recv_prep failed: %d\n", ret);
220*25da2beaSAndroid Build Coastguard Worker 		goto err;
221*25da2beaSAndroid Build Coastguard Worker 	}
222*25da2beaSAndroid Build Coastguard Worker 	ret = do_recv(&ring);
223*25da2beaSAndroid Build Coastguard Worker 	if (!ret) {
224*25da2beaSAndroid Build Coastguard Worker 		int i;
225*25da2beaSAndroid Build Coastguard Worker 
226*25da2beaSAndroid Build Coastguard Worker 		for (i = 0; i < MAX_MSG; i++) {
227*25da2beaSAndroid Build Coastguard Worker 			if (buf[i] != i) {
228*25da2beaSAndroid Build Coastguard Worker 				fprintf(stderr, "found %d at %d\n", buf[i], i);
229*25da2beaSAndroid Build Coastguard Worker 				ret = 1;
230*25da2beaSAndroid Build Coastguard Worker 				break;
231*25da2beaSAndroid Build Coastguard Worker 			}
232*25da2beaSAndroid Build Coastguard Worker 		}
233*25da2beaSAndroid Build Coastguard Worker 	}
234*25da2beaSAndroid Build Coastguard Worker 
235*25da2beaSAndroid Build Coastguard Worker 	shutdown(sockout, SHUT_RDWR);
236*25da2beaSAndroid Build Coastguard Worker 	shutdown(sock, SHUT_RDWR);
237*25da2beaSAndroid Build Coastguard Worker 	close(sock);
238*25da2beaSAndroid Build Coastguard Worker 	close(sockout);
239*25da2beaSAndroid Build Coastguard Worker 	io_uring_queue_exit(&ring);
240*25da2beaSAndroid Build Coastguard Worker err:
241*25da2beaSAndroid Build Coastguard Worker 	if (sock != -1) {
242*25da2beaSAndroid Build Coastguard Worker 		shutdown(sock, SHUT_RDWR);
243*25da2beaSAndroid Build Coastguard Worker 		close(sock);
244*25da2beaSAndroid Build Coastguard Worker 	}
245*25da2beaSAndroid Build Coastguard Worker 	if (sockout != -1) {
246*25da2beaSAndroid Build Coastguard Worker 		shutdown(sockout, SHUT_RDWR);
247*25da2beaSAndroid Build Coastguard Worker 		close(sockout);
248*25da2beaSAndroid Build Coastguard Worker 	}
249*25da2beaSAndroid Build Coastguard Worker 	return ret;
250*25da2beaSAndroid Build Coastguard Worker }
251*25da2beaSAndroid Build Coastguard Worker 
recv_fn(void * data)252*25da2beaSAndroid Build Coastguard Worker static void *recv_fn(void *data)
253*25da2beaSAndroid Build Coastguard Worker {
254*25da2beaSAndroid Build Coastguard Worker 	struct recv_data *rd = data;
255*25da2beaSAndroid Build Coastguard Worker 
256*25da2beaSAndroid Build Coastguard Worker 	if (rd->use_sync)
257*25da2beaSAndroid Build Coastguard Worker 		return (void *) (uintptr_t) recv_sync(rd);
258*25da2beaSAndroid Build Coastguard Worker 
259*25da2beaSAndroid Build Coastguard Worker 	return (void *) (uintptr_t) recv_uring(rd);
260*25da2beaSAndroid Build Coastguard Worker }
261*25da2beaSAndroid Build Coastguard Worker 
do_send(struct recv_data * rd)262*25da2beaSAndroid Build Coastguard Worker static int do_send(struct recv_data *rd)
263*25da2beaSAndroid Build Coastguard Worker {
264*25da2beaSAndroid Build Coastguard Worker 	struct sockaddr_in saddr;
265*25da2beaSAndroid Build Coastguard Worker 	struct io_uring ring;
266*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_cqe *cqe;
267*25da2beaSAndroid Build Coastguard Worker 	struct io_uring_sqe *sqe;
268*25da2beaSAndroid Build Coastguard Worker 	int sockfd, ret, i;
269*25da2beaSAndroid Build Coastguard Worker 	struct iovec iov;
270*25da2beaSAndroid Build Coastguard Worker 	int *buf;
271*25da2beaSAndroid Build Coastguard Worker 
272*25da2beaSAndroid Build Coastguard Worker 	ret = io_uring_queue_init(2, &ring, 0);
273*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
274*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "queue init failed: %d\n", ret);
275*25da2beaSAndroid Build Coastguard Worker 		return 1;
276*25da2beaSAndroid Build Coastguard Worker 	}
277*25da2beaSAndroid Build Coastguard Worker 
278*25da2beaSAndroid Build Coastguard Worker 	buf = malloc(MAX_MSG * sizeof(int));
279*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < MAX_MSG; i++)
280*25da2beaSAndroid Build Coastguard Worker 		buf[i] = i;
281*25da2beaSAndroid Build Coastguard Worker 
282*25da2beaSAndroid Build Coastguard Worker 	memset(&saddr, 0, sizeof(saddr));
283*25da2beaSAndroid Build Coastguard Worker 	saddr.sin_family = AF_INET;
284*25da2beaSAndroid Build Coastguard Worker 	saddr.sin_port = htons(rd->port);
285*25da2beaSAndroid Build Coastguard Worker 	inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr);
286*25da2beaSAndroid Build Coastguard Worker 
287*25da2beaSAndroid Build Coastguard Worker 	sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
288*25da2beaSAndroid Build Coastguard Worker 	if (sockfd < 0) {
289*25da2beaSAndroid Build Coastguard Worker 		perror("socket");
290*25da2beaSAndroid Build Coastguard Worker 		return 1;
291*25da2beaSAndroid Build Coastguard Worker 	}
292*25da2beaSAndroid Build Coastguard Worker 
293*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_lock(&rd->mutex);
294*25da2beaSAndroid Build Coastguard Worker 
295*25da2beaSAndroid Build Coastguard Worker 	ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
296*25da2beaSAndroid Build Coastguard Worker 	if (ret < 0) {
297*25da2beaSAndroid Build Coastguard Worker 		perror("connect");
298*25da2beaSAndroid Build Coastguard Worker 		return 1;
299*25da2beaSAndroid Build Coastguard Worker 	}
300*25da2beaSAndroid Build Coastguard Worker 
301*25da2beaSAndroid Build Coastguard Worker 	iov.iov_base = buf;
302*25da2beaSAndroid Build Coastguard Worker 	iov.iov_len = MAX_MSG * sizeof(int) / 2;
303*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 2; i++) {
304*25da2beaSAndroid Build Coastguard Worker 		sqe = io_uring_get_sqe(&ring);
305*25da2beaSAndroid Build Coastguard Worker 		io_uring_prep_send(sqe, sockfd, iov.iov_base, iov.iov_len, 0);
306*25da2beaSAndroid Build Coastguard Worker 		sqe->user_data = 1;
307*25da2beaSAndroid Build Coastguard Worker 
308*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_submit(&ring);
309*25da2beaSAndroid Build Coastguard Worker 		if (ret <= 0) {
310*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "submit failed: %d\n", ret);
311*25da2beaSAndroid Build Coastguard Worker 			goto err;
312*25da2beaSAndroid Build Coastguard Worker 		}
313*25da2beaSAndroid Build Coastguard Worker 		usleep(10000);
314*25da2beaSAndroid Build Coastguard Worker 		iov.iov_base += iov.iov_len;
315*25da2beaSAndroid Build Coastguard Worker 	}
316*25da2beaSAndroid Build Coastguard Worker 
317*25da2beaSAndroid Build Coastguard Worker 	for (i = 0; i < 2; i++) {
318*25da2beaSAndroid Build Coastguard Worker 		ret = io_uring_wait_cqe(&ring, &cqe);
319*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res == -EINVAL) {
320*25da2beaSAndroid Build Coastguard Worker 			fprintf(stdout, "send not supported, skipping\n");
321*25da2beaSAndroid Build Coastguard Worker 			close(sockfd);
322*25da2beaSAndroid Build Coastguard Worker 			return 0;
323*25da2beaSAndroid Build Coastguard Worker 		}
324*25da2beaSAndroid Build Coastguard Worker 		if (cqe->res != iov.iov_len) {
325*25da2beaSAndroid Build Coastguard Worker 			fprintf(stderr, "failed cqe: %d\n", cqe->res);
326*25da2beaSAndroid Build Coastguard Worker 			goto err;
327*25da2beaSAndroid Build Coastguard Worker 		}
328*25da2beaSAndroid Build Coastguard Worker 		io_uring_cqe_seen(&ring, cqe);
329*25da2beaSAndroid Build Coastguard Worker 	}
330*25da2beaSAndroid Build Coastguard Worker 
331*25da2beaSAndroid Build Coastguard Worker 	shutdown(sockfd, SHUT_RDWR);
332*25da2beaSAndroid Build Coastguard Worker 	close(sockfd);
333*25da2beaSAndroid Build Coastguard Worker 	return 0;
334*25da2beaSAndroid Build Coastguard Worker err:
335*25da2beaSAndroid Build Coastguard Worker 	shutdown(sockfd, SHUT_RDWR);
336*25da2beaSAndroid Build Coastguard Worker 	close(sockfd);
337*25da2beaSAndroid Build Coastguard Worker 	return 1;
338*25da2beaSAndroid Build Coastguard Worker }
339*25da2beaSAndroid Build Coastguard Worker 
test(int use_recvmsg,int use_sync)340*25da2beaSAndroid Build Coastguard Worker static int test(int use_recvmsg, int use_sync)
341*25da2beaSAndroid Build Coastguard Worker {
342*25da2beaSAndroid Build Coastguard Worker 	pthread_mutexattr_t attr;
343*25da2beaSAndroid Build Coastguard Worker 	pthread_t recv_thread;
344*25da2beaSAndroid Build Coastguard Worker 	struct recv_data rd;
345*25da2beaSAndroid Build Coastguard Worker 	int ret;
346*25da2beaSAndroid Build Coastguard Worker 	void *retval;
347*25da2beaSAndroid Build Coastguard Worker 
348*25da2beaSAndroid Build Coastguard Worker 	pthread_mutexattr_init(&attr);
349*25da2beaSAndroid Build Coastguard Worker 	pthread_mutexattr_setpshared(&attr, 1);
350*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_init(&rd.mutex, &attr);
351*25da2beaSAndroid Build Coastguard Worker 	pthread_mutex_lock(&rd.mutex);
352*25da2beaSAndroid Build Coastguard Worker 	rd.use_recvmsg = use_recvmsg;
353*25da2beaSAndroid Build Coastguard Worker 	rd.use_sync = use_sync;
354*25da2beaSAndroid Build Coastguard Worker 	rd.port = port++;
355*25da2beaSAndroid Build Coastguard Worker 
356*25da2beaSAndroid Build Coastguard Worker 	ret = pthread_create(&recv_thread, NULL, recv_fn, &rd);
357*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
358*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "Thread create failed: %d\n", ret);
359*25da2beaSAndroid Build Coastguard Worker 		pthread_mutex_unlock(&rd.mutex);
360*25da2beaSAndroid Build Coastguard Worker 		return 1;
361*25da2beaSAndroid Build Coastguard Worker 	}
362*25da2beaSAndroid Build Coastguard Worker 
363*25da2beaSAndroid Build Coastguard Worker 	do_send(&rd);
364*25da2beaSAndroid Build Coastguard Worker 	pthread_join(recv_thread, &retval);
365*25da2beaSAndroid Build Coastguard Worker 	return (intptr_t)retval;
366*25da2beaSAndroid Build Coastguard Worker }
367*25da2beaSAndroid Build Coastguard Worker 
main(int argc,char * argv[])368*25da2beaSAndroid Build Coastguard Worker int main(int argc, char *argv[])
369*25da2beaSAndroid Build Coastguard Worker {
370*25da2beaSAndroid Build Coastguard Worker 	int ret;
371*25da2beaSAndroid Build Coastguard Worker 
372*25da2beaSAndroid Build Coastguard Worker 	if (argc > 1)
373*25da2beaSAndroid Build Coastguard Worker 		return 0;
374*25da2beaSAndroid Build Coastguard Worker 
375*25da2beaSAndroid Build Coastguard Worker 	ret = test(0, 0);
376*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
377*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test recv failed\n");
378*25da2beaSAndroid Build Coastguard Worker 		return ret;
379*25da2beaSAndroid Build Coastguard Worker 	}
380*25da2beaSAndroid Build Coastguard Worker 
381*25da2beaSAndroid Build Coastguard Worker 	ret = test(1, 0);
382*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
383*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test recvmsg failed\n");
384*25da2beaSAndroid Build Coastguard Worker 		return ret;
385*25da2beaSAndroid Build Coastguard Worker 	}
386*25da2beaSAndroid Build Coastguard Worker 
387*25da2beaSAndroid Build Coastguard Worker 	ret = test(0, 1);
388*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
389*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test sync recv failed\n");
390*25da2beaSAndroid Build Coastguard Worker 		return ret;
391*25da2beaSAndroid Build Coastguard Worker 	}
392*25da2beaSAndroid Build Coastguard Worker 
393*25da2beaSAndroid Build Coastguard Worker 	ret = test(1, 1);
394*25da2beaSAndroid Build Coastguard Worker 	if (ret) {
395*25da2beaSAndroid Build Coastguard Worker 		fprintf(stderr, "test sync recvmsg failed\n");
396*25da2beaSAndroid Build Coastguard Worker 		return ret;
397*25da2beaSAndroid Build Coastguard Worker 	}
398*25da2beaSAndroid Build Coastguard Worker 
399*25da2beaSAndroid Build Coastguard Worker 	return 0;
400*25da2beaSAndroid Build Coastguard Worker }
401