xref: /haiku/src/tests/system/network/ipv6/tcp_udp_server.cpp (revision 5e54f6d4f9dd607ae2afcea4fe72f2f1763e4b5e)
1 /*
2  * Copyright 2010, Atis Elsts, the.kfx@gmail.com
3  * Distributed under the terms of the MIT license.
4  */
5 
6 
7 #include <unistd.h>
8 #include <memory.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 
16 const unsigned short TEST_PORT = 40000;
17 
18 
19 void
usage()20 usage()
21 {
22 	printf("server [tcp|udp] [4|6] [local-address]\n");
23 	exit(1);
24 }
25 
26 
27 void
recvLoop(int fd)28 recvLoop(int fd)
29 {
30 	for (;;)	{
31 		char buffer[1000];
32 		int status = recv(fd, buffer, sizeof(buffer) - 1, 0);
33 		if (status < 0) {
34 			perror("recv");
35 			exit(-1);
36 		}
37 		if (status == 0) {
38 			printf("received EOF!\n");
39 			break;
40 		} else {
41 			buffer[status] = 0;
42 			printf("received %d bytes: \"%s\"\n", status, buffer);
43 		}
44 	}
45 }
46 
47 
48 int
main(int argc,char * argv[])49 main(int argc, char *argv[])
50 {
51 	int socketType = SOCK_DGRAM;
52 	int socketFamily = AF_INET;
53 	if (argc > 1) {
54 		if (!strcmp(argv[1], "tcp"))
55 			socketType = SOCK_STREAM;
56 		else if (!strcmp(argv[1], "udp"))
57 			socketType = SOCK_DGRAM;
58 		else
59 			usage();
60 	}
61 	if (argc > 2) {
62 		switch (atoi(argv[2])) {
63 		case 4:
64 			socketFamily = AF_INET;
65 			break;
66 		case 6:
67 			socketFamily = AF_INET6;
68 			break;
69 		default:
70 			usage();
71 		}
72 	}
73 
74 	sockaddr_storage localAddress;
75 	memset(&localAddress, 0, sizeof(localAddress));
76 	localAddress.ss_family = socketFamily;
77 	((sockaddr_in *) &localAddress)->sin_port = htons(TEST_PORT);
78 
79 	if (argc > 3) {
80 		do {
81 			void *dstBuffer = &((sockaddr_in *) &localAddress)->sin_addr;
82 			if (inet_pton(AF_INET, argv[3], dstBuffer) == 1) {
83 				printf("using IPv4 local address\n");
84 				localAddress.ss_family = AF_INET;
85 				break;
86 			}
87 
88 			dstBuffer = &((sockaddr_in6 *) &localAddress)->sin6_addr;
89 			if (inet_pton(AF_INET6, argv[3], dstBuffer) == 1) {
90 				printf("using IPv6 local address\n");
91 				localAddress.ss_family = AF_INET6;
92 				break;
93 			}
94 
95 			usage();
96 		} while (false);
97 	}
98 
99 	int fd = socket(socketFamily, socketType, 0);
100 	if (fd < 0) {
101 		perror("socket");
102 		return -1;
103 	}
104 
105 	if (bind(fd, (sockaddr *)&localAddress, localAddress.ss_family == AF_INET ?
106 			sizeof(sockaddr_in) : sizeof(sockaddr_in6)) < 0) {
107 		perror("bind");
108 		return -1;
109 	}
110 
111 	switch (socketType) {
112 	case SOCK_DGRAM:
113 		for (;;)
114 			recvLoop(fd);
115 		break;
116 	case SOCK_STREAM:
117 		if (listen(fd, 5) < 0) {
118 			perror("listen");
119 			return 1;
120 		}
121 		for (;;) {
122 			int clientfd = accept(fd, NULL, 0);
123 			if (clientfd < 0) {
124 				perror("accept");
125 				return 1;
126 			}
127 			printf("TCP server: got some client!\n");
128 			if (fork() != 0) {
129 				// parent code
130 				close(clientfd);
131 				continue;
132 			}
133 			// child code
134 			close(fd);
135 			recvLoop(clientfd);
136 			exit(0);
137 		}
138 		break;
139 	}
140 }
141