1f012ee0cSGordon Ross /*
2f012ee0cSGordon Ross  * Copyright 2016 Jeremy Allison
3f012ee0cSGordon Ross  *
4f012ee0cSGordon Ross  * Permission is hereby granted, free of charge, to any person obtaining a
5f012ee0cSGordon Ross  * copy of this software and associated documentation files (the "Software"),
6f012ee0cSGordon Ross  * to deal in the Software without restriction, including without limitation
7f012ee0cSGordon Ross  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f012ee0cSGordon Ross  * and/or sell copies of the Software, and to permit persons to whom the
9f012ee0cSGordon Ross  * Software is furnished to do so, subject to the following conditions:
10f012ee0cSGordon Ross  *
11f012ee0cSGordon Ross  * The above copyright notice and this permission notice shall be included
12f012ee0cSGordon Ross  * in all copies or substantial portions of the Software.
13f012ee0cSGordon Ross  *
14f012ee0cSGordon Ross  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15f012ee0cSGordon Ross  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16f012ee0cSGordon Ross  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17f012ee0cSGordon Ross  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18f012ee0cSGordon Ross  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19f012ee0cSGordon Ross  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20f012ee0cSGordon Ross  * DEALINGS IN THE SOFTWARE.
21f012ee0cSGordon Ross  */
22f012ee0cSGordon Ross 
23f012ee0cSGordon Ross #include <sys/param.h>
24f012ee0cSGordon Ross #include <sys/types.h>
25f012ee0cSGordon Ross #include <sys/stat.h>
26f012ee0cSGordon Ross #include <sys/socket.h>
27f012ee0cSGordon Ross #include <sys/un.h>
28f012ee0cSGordon Ross #include <stdio.h>
29f012ee0cSGordon Ross #include <unistd.h>
30f012ee0cSGordon Ross #include <string.h>
31f012ee0cSGordon Ross #include <errno.h>
32f012ee0cSGordon Ross #include <stdint.h>
33f012ee0cSGordon Ross #include <stdlib.h>
34f012ee0cSGordon Ross #include <pthread.h>
35f012ee0cSGordon Ross 
36*b521c41bSGordon Ross extern char *__progname;
37*b521c41bSGordon Ross 
38f012ee0cSGordon Ross static void *
server(void * varg)39f012ee0cSGordon Ross server(void *varg)
40f012ee0cSGordon Ross {
41f012ee0cSGordon Ross 	int *sfds = (int *)varg;
42f012ee0cSGordon Ross 	int ret;
43f012ee0cSGordon Ross 	int sock = sfds[0];
44f012ee0cSGordon Ross 	unsigned int i;
45f012ee0cSGordon Ross 
46f012ee0cSGordon Ross 	for (i = 0; i < 5; i++) {
47f012ee0cSGordon Ross 		struct iovec iov;
48f012ee0cSGordon Ross 		struct msghdr msg;
49f012ee0cSGordon Ross 		uint8_t buf[4096];
50f012ee0cSGordon Ross 
51f012ee0cSGordon Ross 		iov = (struct iovec) {
52f012ee0cSGordon Ross 			.iov_base = buf,
53f012ee0cSGordon Ross 			.iov_len = sizeof (buf)
54f012ee0cSGordon Ross 		};
55f012ee0cSGordon Ross 
56f012ee0cSGordon Ross 		msg = (struct msghdr) {
57f012ee0cSGordon Ross 			.msg_iov = &iov,
58f012ee0cSGordon Ross 			.msg_iovlen = 1,
59f012ee0cSGordon Ross 		};
60f012ee0cSGordon Ross 
61f012ee0cSGordon Ross 		ret = recvmsg(sock, &msg, 0);
62f012ee0cSGordon Ross 		if (ret == -1) {
63f012ee0cSGordon Ross 			fprintf(stderr, "server - recvmsg fail %s\n",
64f012ee0cSGordon Ross 			    strerror(errno));
65f012ee0cSGordon Ross 			exit(1);
66f012ee0cSGordon Ross 		}
67*b521c41bSGordon Ross 		if (ret == 0) {
68*b521c41bSGordon Ross 			printf("SERVER: got HUP\n");
69*b521c41bSGordon Ross 			break;
70*b521c41bSGordon Ross 		}
71f012ee0cSGordon Ross 
72f012ee0cSGordon Ross 		printf("SERVER:%s\n", (char *)msg.msg_iov->iov_base);
73f012ee0cSGordon Ross 		fflush(stdout);
74f012ee0cSGordon Ross 	}
75f012ee0cSGordon Ross 
76*b521c41bSGordon Ross 	close(sock);
77*b521c41bSGordon Ross 	return (NULL);
78f012ee0cSGordon Ross }
79f012ee0cSGordon Ross 
80*b521c41bSGordon Ross void
runtest(int sotype)81*b521c41bSGordon Ross runtest(int sotype)
82f012ee0cSGordon Ross {
83f012ee0cSGordon Ross 	int sfds[2];
84f012ee0cSGordon Ross 	int sock;
85*b521c41bSGordon Ross 	int ret;
86f012ee0cSGordon Ross 	unsigned int i;
87f012ee0cSGordon Ross 
88f012ee0cSGordon Ross 	/* Create socketpair */
89*b521c41bSGordon Ross 	ret = socketpair(AF_UNIX, sotype, 0, sfds);
90f012ee0cSGordon Ross 	if (ret == -1) {
91f012ee0cSGordon Ross 		fprintf(stderr, "%s - socketpair fail %s\n",
92*b521c41bSGordon Ross 		    __progname, strerror(errno));
93f012ee0cSGordon Ross 		exit(1);
94f012ee0cSGordon Ross 	}
95f012ee0cSGordon Ross 
96*b521c41bSGordon Ross 	/* Set up the server.  It closes sfds[0] when done. */
97f012ee0cSGordon Ross 	ret = pthread_create(NULL, NULL, server, sfds);
98f012ee0cSGordon Ross 	if (ret == -1) {
99f012ee0cSGordon Ross 		fprintf(stderr, "%s - thread create fail %s\n",
100*b521c41bSGordon Ross 		    __progname, strerror(errno));
101f012ee0cSGordon Ross 		exit(1);
102f012ee0cSGordon Ross 	}
103f012ee0cSGordon Ross 
104f012ee0cSGordon Ross 	sleep(1);
105f012ee0cSGordon Ross 
106f012ee0cSGordon Ross 	/* "Server" is sfds[0], "client" is sfds[1] */
107f012ee0cSGordon Ross 	sock = sfds[1];
108f012ee0cSGordon Ross 
109f012ee0cSGordon Ross 	/* Send some messages */
110*b521c41bSGordon Ross 	for (i = 0; i < 3; i++) {
111f012ee0cSGordon Ross 		struct iovec iov;
112f012ee0cSGordon Ross 		struct msghdr msg;
113f012ee0cSGordon Ross 		uint8_t buf[4096];
114f012ee0cSGordon Ross 
115f012ee0cSGordon Ross 		memcpy(buf, "TEST0", sizeof ("TEST0"));
116f012ee0cSGordon Ross 		buf[4] = '0' + i;
117f012ee0cSGordon Ross 
118f012ee0cSGordon Ross 		printf("CLIENT:%s\n", buf);
119f012ee0cSGordon Ross 
120f012ee0cSGordon Ross 		iov = (struct iovec) {
121f012ee0cSGordon Ross 			.iov_base = buf,
122f012ee0cSGordon Ross 			.iov_len = sizeof (buf),
123f012ee0cSGordon Ross 		};
124f012ee0cSGordon Ross 
125f012ee0cSGordon Ross 		msg = (struct msghdr) {
126f012ee0cSGordon Ross 			.msg_iov = &iov,
127f012ee0cSGordon Ross 			.msg_iovlen = 1,
128f012ee0cSGordon Ross 		};
129f012ee0cSGordon Ross 
130f012ee0cSGordon Ross 		ret = sendmsg(sock, &msg, 0);
131f012ee0cSGordon Ross 
132f012ee0cSGordon Ross 		if (ret == -1) {
133f012ee0cSGordon Ross 			fprintf(stderr, "%s - sendmsg fail %s\n",
134*b521c41bSGordon Ross 			    __progname, strerror(errno));
135f012ee0cSGordon Ross 			exit(1);
136f012ee0cSGordon Ross 		}
137f012ee0cSGordon Ross 
138f012ee0cSGordon Ross 		fflush(stdout);
139f012ee0cSGordon Ross 		sleep(1);
140f012ee0cSGordon Ross 	}
141f012ee0cSGordon Ross 
142*b521c41bSGordon Ross 	/*
143*b521c41bSGordon Ross 	 * Tell sever to terminate
144*b521c41bSGordon Ross 	 */
145*b521c41bSGordon Ross 	if (sotype == SOCK_STREAM) {
146*b521c41bSGordon Ross 		printf("CLIENT: close\n");
147*b521c41bSGordon Ross 		close(sock);
148*b521c41bSGordon Ross 	} else {
149*b521c41bSGordon Ross 		printf("CLIENT: send 0\n");
150*b521c41bSGordon Ross 		send(sock, "", 0, 0);
151*b521c41bSGordon Ross 	}
152*b521c41bSGordon Ross 	sleep(1);
153*b521c41bSGordon Ross }
154*b521c41bSGordon Ross 
155*b521c41bSGordon Ross int
main(int argc,char ** argv)156*b521c41bSGordon Ross main(int argc, char **argv)
157*b521c41bSGordon Ross {
158*b521c41bSGordon Ross 
159*b521c41bSGordon Ross 	printf("%s SOCK_STREAM test...\n", argv[0]);
160*b521c41bSGordon Ross 	runtest(SOCK_STREAM);
161*b521c41bSGordon Ross 
162*b521c41bSGordon Ross 	printf("%s SOCK_DGRAM test...\n", argv[0]);
163*b521c41bSGordon Ross 	runtest(SOCK_DGRAM);
164*b521c41bSGordon Ross 
165f012ee0cSGordon Ross 	return (0);
166f012ee0cSGordon Ross }
167