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