1 /* 2 * Server for the sendfile test program 3 * Syntax: testsf_s <own IP addr> 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 #include <fcntl.h> 10 #include <sys/file.h> 11 #include <errno.h> 12 #include <sys/signal.h> 13 #include <sys/types.h> 14 #include <arpa/inet.h> 15 #include <netinet/in.h> 16 #include <sys/sendfile.h> 17 #include <sys/socket.h> 18 #include <sys/wait.h> 19 #include "test.h" 20 #include "netdefs.h" 21 22 int TST_TOTAL = 1; 23 24 #if INET6 25 char *TCID = "sendfile6_server"; 26 #else 27 char *TCID = "sendfile_server"; 28 #endif 29 30 int main(int argc, char *argv[]) 31 { 32 sai_t sa, *ap; 33 sa_t from; 34 struct addrinfo *hp; 35 struct addrinfo hints; 36 int as, fd, gai, rc, s; 37 char *lp; 38 char *number; 39 int pid, nbytes, flen, count; 40 char rbuf[PATH_MAX]; 41 int chunks = 0; 42 off_t *offset; 43 char nbuf[PATH_MAX]; 44 int port; 45 46 if (argc != 3) { 47 tst_brkm(TBROK, NULL, "usage: listen-address listen-port"); 48 } 49 50 /* open socket */ 51 if ((s = socket(AFI, SOCK_STREAM, 0)) < 0) { 52 tst_brkm(TBROK, NULL, "socket error = %d\n", errno); 53 } 54 55 signal(SIGCHLD, SIG_IGN); /* ignore signals from children */ 56 57 memset(&hints, 0, sizeof(hints)); 58 hints.ai_family = PFI; 59 if ((gai = getaddrinfo(argv[1], NULL, &hints, &hp)) != 0) { 60 tst_brkm(TBROK, NULL, "getaddrinfo failed"); 61 } 62 if (!hp || !hp->ai_addr || hp->ai_addr->sa_family != AFI) { 63 tst_brkm(TBROK, NULL, "getaddrinfo failed"); 64 } 65 66 /* server IP and port */ 67 memcpy(&sa, hp->ai_addr, hp->ai_addrlen); 68 port = atoi(argv[2]); 69 #if INET6 70 sa.sin6_port = htons(port); 71 #else 72 sa.sin_port = htons(port); 73 #endif 74 75 /* bind IP and port to socket */ 76 if (bind(s, (sa_t *) & sa, sizeof(sa)) < 0) { 77 tst_resm(TBROK, "bind error = %d\n", errno); 78 close(s); 79 tst_exit(); 80 } 81 82 /* start to listen socket */ 83 if (listen(s, LISTEN_BACKLOG) < 0) { 84 tst_resm(TBROK, "listen error = %d\n", errno); 85 close(s); 86 tst_exit(); 87 } 88 89 socklen_t fromlen = sizeof(from); 90 91 /* process connections */ 92 while (1) { 93 94 /* accept a connection from a client */ 95 if ((as = accept(s, &from, &fromlen)) < 0) { 96 tst_resm(TBROK, "accept error = %d\n", errno); 97 if (errno == EINTR) 98 continue; 99 close(s); 100 tst_exit(); 101 } 102 103 ap = (sai_t *) & from; 104 105 /* create a process to manage the connection */ 106 if ((pid = fork()) < 0) { 107 tst_resm(TBROK, "fork error = %d\n", errno); 108 close(as); 109 tst_exit(); 110 } 111 if (pid > 0) { /* parent, go back to accept */ 112 close(as); 113 continue; 114 } 115 116 /* child process to manage a connection */ 117 118 close(s); /* close service socket */ 119 120 /* get client request information */ 121 if ((nbytes = read(as, rbuf, PATH_MAX)) <= 0) { 122 tst_resm(TBROK, "socket read error = %d\n", errno); 123 close(as); 124 tst_exit(); 125 } 126 rbuf[nbytes] = '\0'; /* null terminate the info */ 127 lp = &rbuf[0]; 128 129 /* start with file length, '=' will start the filename */ 130 count = flen = 0; 131 number = &nbuf[0]; 132 while (*lp != '=') { /* convert ascii to integer */ 133 nbuf[count] = *lp; 134 count++; 135 lp++; 136 } 137 nbuf[count] = '\0'; 138 flen = strtol(number, NULL, 10); 139 140 /* the file name */ 141 lp++; 142 143 tst_resm(TINFO, "The file to send is %s\n", lp); 144 /* open requested file to send */ 145 if ((fd = open(lp, O_RDONLY)) < 0) { 146 tst_resm(TBROK, "file open error = %d\n", errno); 147 close(as); 148 tst_exit(); 149 } 150 offset = NULL; 151 errno = 0; 152 do { /* send file parts until EOF */ 153 if ((rc = sendfile(as, fd, offset, flen)) != flen) { 154 if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) { 155 tst_resm(TBROK, 156 "sendfile error = %d, rc = %d\n", 157 errno, rc); 158 close(as); 159 close(fd); 160 tst_exit(); 161 } 162 } 163 chunks++; 164 } while (rc != 0); 165 tst_resm(TINFO, "File %s sent in %d parts\n", lp, chunks); 166 167 close(as); /* close connection */ 168 close(fd); /* close requested file */ 169 170 exit(0); 171 172 } 173 174 close(s); /* close parent socket (never reached because of the while (1)) */ 175 176 tst_exit(); 177 178 } 179