1*5e54f6d4SAugustin Cavalier /*
2*5e54f6d4SAugustin Cavalier * a stream socket server demo
3*5e54f6d4SAugustin Cavalier */
4*5e54f6d4SAugustin Cavalier
5*5e54f6d4SAugustin Cavalier
6*5e54f6d4SAugustin Cavalier #include <arpa/inet.h>
7*5e54f6d4SAugustin Cavalier #include <errno.h>
8*5e54f6d4SAugustin Cavalier #include <netinet/in.h>
9*5e54f6d4SAugustin Cavalier #include <signal.h>
10*5e54f6d4SAugustin Cavalier #include <stdio.h>
11*5e54f6d4SAugustin Cavalier #include <stdlib.h>
12*5e54f6d4SAugustin Cavalier #include <string.h>
13*5e54f6d4SAugustin Cavalier #include <sys/socket.h>
14*5e54f6d4SAugustin Cavalier #include <sys/types.h>
15*5e54f6d4SAugustin Cavalier #include <sys/wait.h>
16*5e54f6d4SAugustin Cavalier #include <unistd.h>
17*5e54f6d4SAugustin Cavalier
18*5e54f6d4SAugustin Cavalier
19*5e54f6d4SAugustin Cavalier #define MYPORT 1234 // the port users will be connecting to
20*5e54f6d4SAugustin Cavalier #define BACKLOG 10 // how many pending connections queue will hold
21*5e54f6d4SAugustin Cavalier #define MAXDATASIZE 1065537
22*5e54f6d4SAugustin Cavalier
23*5e54f6d4SAugustin Cavalier
24*5e54f6d4SAugustin Cavalier static void
sigchld_handler(int s)25*5e54f6d4SAugustin Cavalier sigchld_handler(int s)
26*5e54f6d4SAugustin Cavalier {
27*5e54f6d4SAugustin Cavalier while (waitpid(-1, NULL, WNOHANG) > 0) {
28*5e54f6d4SAugustin Cavalier }
29*5e54f6d4SAugustin Cavalier }
30*5e54f6d4SAugustin Cavalier
31*5e54f6d4SAugustin Cavalier
32*5e54f6d4SAugustin Cavalier int
main(int argc,char * argv[])33*5e54f6d4SAugustin Cavalier main(int argc, char *argv[])
34*5e54f6d4SAugustin Cavalier {
35*5e54f6d4SAugustin Cavalier int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
36*5e54f6d4SAugustin Cavalier struct sockaddr_in my_addr; // my address information
37*5e54f6d4SAugustin Cavalier struct sockaddr_in their_addr; // connector's address information
38*5e54f6d4SAugustin Cavalier uint32_t sin_size;
39*5e54f6d4SAugustin Cavalier struct sigaction sa;
40*5e54f6d4SAugustin Cavalier int yes = 1;
41*5e54f6d4SAugustin Cavalier short int port = MYPORT;
42*5e54f6d4SAugustin Cavalier char buf[MAXDATASIZE];
43*5e54f6d4SAugustin Cavalier
44*5e54f6d4SAugustin Cavalier if (argc >= 2 && atoi(argv[1]) != 0)
45*5e54f6d4SAugustin Cavalier port = atoi(argv[1]);
46*5e54f6d4SAugustin Cavalier
47*5e54f6d4SAugustin Cavalier if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
48*5e54f6d4SAugustin Cavalier perror("socket");
49*5e54f6d4SAugustin Cavalier exit(1);
50*5e54f6d4SAugustin Cavalier }
51*5e54f6d4SAugustin Cavalier
52*5e54f6d4SAugustin Cavalier if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
53*5e54f6d4SAugustin Cavalier perror("setsockopt");
54*5e54f6d4SAugustin Cavalier exit(1);
55*5e54f6d4SAugustin Cavalier }
56*5e54f6d4SAugustin Cavalier
57*5e54f6d4SAugustin Cavalier memset(&my_addr, 0, sizeof(my_addr));
58*5e54f6d4SAugustin Cavalier my_addr.sin_family = AF_INET;
59*5e54f6d4SAugustin Cavalier my_addr.sin_port = htons(port);
60*5e54f6d4SAugustin Cavalier my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
61*5e54f6d4SAugustin Cavalier
62*5e54f6d4SAugustin Cavalier if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
63*5e54f6d4SAugustin Cavalier perror("bind");
64*5e54f6d4SAugustin Cavalier exit(1);
65*5e54f6d4SAugustin Cavalier }
66*5e54f6d4SAugustin Cavalier
67*5e54f6d4SAugustin Cavalier if (listen(sockfd, BACKLOG) == -1) {
68*5e54f6d4SAugustin Cavalier perror("listen");
69*5e54f6d4SAugustin Cavalier exit(1);
70*5e54f6d4SAugustin Cavalier }
71*5e54f6d4SAugustin Cavalier
72*5e54f6d4SAugustin Cavalier sa.sa_handler = sigchld_handler; // reap all dead processes
73*5e54f6d4SAugustin Cavalier sigemptyset(&sa.sa_mask);
74*5e54f6d4SAugustin Cavalier #ifdef HAIKU_TARGET_PLATFORM_HAIKU
75*5e54f6d4SAugustin Cavalier sa.sa_flags = SA_RESTART;
76*5e54f6d4SAugustin Cavalier #else
77*5e54f6d4SAugustin Cavalier sa.sa_flags = 0;
78*5e54f6d4SAugustin Cavalier #endif
79*5e54f6d4SAugustin Cavalier if (sigaction(SIGCHLD, &sa, NULL) == -1) {
80*5e54f6d4SAugustin Cavalier perror("sigaction");
81*5e54f6d4SAugustin Cavalier exit(1);
82*5e54f6d4SAugustin Cavalier }
83*5e54f6d4SAugustin Cavalier
84*5e54f6d4SAugustin Cavalier while (1) {
85*5e54f6d4SAugustin Cavalier // main accept() loop
86*5e54f6d4SAugustin Cavalier sin_size = sizeof(struct sockaddr_in);
87*5e54f6d4SAugustin Cavalier if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
88*5e54f6d4SAugustin Cavalier perror("accept");
89*5e54f6d4SAugustin Cavalier continue;
90*5e54f6d4SAugustin Cavalier }
91*5e54f6d4SAugustin Cavalier printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
92*5e54f6d4SAugustin Cavalier if (!fork()) { // this is the child process
93*5e54f6d4SAugustin Cavalier close(sockfd); // child doesn't need the listener
94*5e54f6d4SAugustin Cavalier
95*5e54f6d4SAugustin Cavalier if (!fork()) {
96*5e54f6d4SAugustin Cavalier while (1) {
97*5e54f6d4SAugustin Cavalier // child's child process
98*5e54f6d4SAugustin Cavalier if (fgets(buf, MAXDATASIZE, stdin) == NULL) {
99*5e54f6d4SAugustin Cavalier perror("fgets");
100*5e54f6d4SAugustin Cavalier exit(1);
101*5e54f6d4SAugustin Cavalier }
102*5e54f6d4SAugustin Cavalier
103*5e54f6d4SAugustin Cavalier if (!strcmp(buf, "full\n")) {
104*5e54f6d4SAugustin Cavalier int i;
105*5e54f6d4SAugustin Cavalier puts("HY");
106*5e54f6d4SAugustin Cavalier for (i = 0; i < MAXDATASIZE - 2; i++) {
107*5e54f6d4SAugustin Cavalier buf[i] = 'a' + (i % 26);
108*5e54f6d4SAugustin Cavalier }
109*5e54f6d4SAugustin Cavalier buf[MAXDATASIZE - 2] = '\n';
110*5e54f6d4SAugustin Cavalier buf[MAXDATASIZE - 1] = '\0';
111*5e54f6d4SAugustin Cavalier }
112*5e54f6d4SAugustin Cavalier
113*5e54f6d4SAugustin Cavalier if (send(new_fd, buf, strlen(buf), 0) == -1) {
114*5e54f6d4SAugustin Cavalier perror("send");
115*5e54f6d4SAugustin Cavalier exit(1);
116*5e54f6d4SAugustin Cavalier }
117*5e54f6d4SAugustin Cavalier }
118*5e54f6d4SAugustin Cavalier } else {
119*5e54f6d4SAugustin Cavalier ssize_t numBytes;
120*5e54f6d4SAugustin Cavalier while (1) {
121*5e54f6d4SAugustin Cavalier // child process
122*5e54f6d4SAugustin Cavalier if ((numBytes = recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
123*5e54f6d4SAugustin Cavalier perror("recv");
124*5e54f6d4SAugustin Cavalier exit(1);
125*5e54f6d4SAugustin Cavalier }
126*5e54f6d4SAugustin Cavalier if (numBytes == 0)
127*5e54f6d4SAugustin Cavalier exit(0);
128*5e54f6d4SAugustin Cavalier
129*5e54f6d4SAugustin Cavalier buf[numBytes] = '\0';
130*5e54f6d4SAugustin Cavalier
131*5e54f6d4SAugustin Cavalier printf("%s:| %s", inet_ntoa(their_addr.sin_addr), buf);
132*5e54f6d4SAugustin Cavalier }
133*5e54f6d4SAugustin Cavalier }
134*5e54f6d4SAugustin Cavalier
135*5e54f6d4SAugustin Cavalier close(new_fd);
136*5e54f6d4SAugustin Cavalier exit(0);
137*5e54f6d4SAugustin Cavalier }
138*5e54f6d4SAugustin Cavalier close(new_fd); // parent doesn't need this
139*5e54f6d4SAugustin Cavalier }
140*5e54f6d4SAugustin Cavalier
141*5e54f6d4SAugustin Cavalier return 0;
142*5e54f6d4SAugustin Cavalier }
143*5e54f6d4SAugustin Cavalier
144