1#include <errno.h>
2#include <fcntl.h>
3#include <netinet/in.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/socket.h>
8#include <sys/uio.h>
9#include <unistd.h>
10
11
12int
13main(int argc, const char* const* argv)
14{
15	// create the listener socket
16	int listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
17	if (listenerSocket < 0) {
18		fprintf(stderr, "failed to create listener socket: %s\n",
19			strerror(errno));
20		exit(1);
21	}
22
23	// bind it to the port
24	sockaddr_in addr;
25	addr.sin_family = AF_INET;
26	addr.sin_addr.s_addr = INADDR_ANY;
27	addr.sin_port = 0;
28	socklen_t addrLen = sizeof(addr);
29	if (bind(listenerSocket, (sockaddr*)&addr, addrLen) < 0) {
30		fprintf(stderr, "failed to bind listener socket: %s\n",
31			strerror(errno));
32		exit(1);
33	}
34
35 	memset(&addr, 0, sizeof(addr));
36 	addrLen = sizeof(addr);
37 	if (getsockname(listenerSocket, (sockaddr*)&addr, &addrLen) != 0) {
38 		fprintf(stderr, "failed to get socket name: %s\n", strerror(errno));
39 		exit(1);
40 	}
41
42	printf("listener port: %d (%x)\n", addr.sin_port, addr.sin_addr.s_addr);
43
44	// start listening
45	if (listen(listenerSocket, 1) < 0) {
46		return -1;
47	}
48
49	// fork client
50	pid_t child = fork();
51	if (child < 0) {
52		fprintf(stderr, "fork() failed: %s\n", strerror(errno));
53		exit(1);
54	}
55
56	if (child == 0) {
57		// child
58		unsigned short previousPort = 0;
59
60		for (int i = 0; ; i++) {
61			// create the client socket
62			int fd = socket(AF_INET, SOCK_STREAM, 0);
63			if (fd < 0) {
64				fprintf(stderr, "child: %d: failed to create client socket: "
65					"%s\n", i, strerror(errno));
66				exit(1);
67			}
68
69/*
70			// test binding
71			if (previousPort != 0) {
72				sockaddr_in clientAddr;
73				clientAddr.sin_family = AF_INET;
74				clientAddr.sin_addr.s_addr = INADDR_ANY;
75//				clientAddr.sin_addr.s_addr = INADDR_LOOPBACK;
76//				clientAddr.sin_port = htons(previousPort);
77//				clientAddr.sin_port = htons(previousPort + 1);
78				clientAddr.sin_port = htons(25432);
79				if (bind(fd, (sockaddr*)&clientAddr, sizeof(clientAddr)) < 0) {
80					fprintf(stderr, "child: %d: failed to bind: %s\n",
81						i, strerror(errno));
82				}
83			}
84*/
85
86			// connect to server
87			if (connect(fd, (sockaddr*)&addr, addrLen) == 0) {
88				sockaddr_in serverAddr;
89				socklen_t serverAddrLen = sizeof(serverAddr);
90				sockaddr_in clientAddr;
91				socklen_t clientAddrLen = sizeof(clientAddr);
92				if (getsockname(fd, (sockaddr*)&clientAddr, &clientAddrLen)
93						== 0
94					&& getpeername(fd, (sockaddr*)&serverAddr, &serverAddrLen)
95						== 0) {
96					previousPort = ntohs(clientAddr.sin_port);
97					printf("child: %d: connected to server: 0x%08x:%u, "
98						"local port: %u\n", i,
99						(unsigned)ntohl(serverAddr.sin_addr.s_addr),
100						ntohs(serverAddr.sin_port),
101						previousPort);
102				} else {
103					fprintf(stderr, "child: %d: failed to get socket name %s\n",
104						i, strerror(errno));
105				}
106			} else {
107				fprintf(stderr, "child: %d: connect() failed %s\n", i,
108					strerror(errno));
109			}
110
111			// wait for the other end to be closed
112			char buffer[1];
113			if (fd >= 0) {
114				read(fd, buffer, sizeof(buffer));
115				close(fd);
116			}
117
118//			close(fd);
119//			sleep(1);
120		}
121	} else {
122		// parent
123		while (true) {
124			// accept a socket
125			int fd = accept(listenerSocket, NULL, 0);
126			if (fd < 0) {
127				fprintf(stderr, "server: accept() failed: %s\n",
128					strerror(errno));
129				exit(1);
130			}
131
132			// wait for it to be closed
133//			char buffer[1];
134//			read(fd, buffer, sizeof(buffer));
135//			close(fd);
136
137			sleep(1);
138			close(fd);
139		}
140	}
141
142	printf("Everything went fine.\n");
143
144	return 0;
145}
146