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