blob: 17e98adc2b7280dea97bbd053378d1d728655792 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
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 <sys/file.h>
robbiewa70576c2003-03-04 18:33:41 +000010#include <errno.h>
plars865695b2001-08-27 22:15:12 +000011#include <sys/signal.h>
robbiew22853aa2002-04-18 16:15:34 +000012#include <sys/types.h>
robbiew34690e52005-10-03 17:51:17 +000013#include <arpa/inet.h>
plars865695b2001-08-27 22:15:12 +000014#include <netinet/in.h>
robbiew34690e52005-10-03 17:51:17 +000015#include <sys/sendfile.h>
plars865695b2001-08-27 22:15:12 +000016#include <sys/socket.h>
robbiew34690e52005-10-03 17:51:17 +000017#include <sys/wait.h>
iyermanoj72aa2aa2003-06-09 19:31:17 +000018#include "test.h"
yaberauneyaef772532009-10-09 17:55:43 +000019#include "netdefs.h"
iyermanoj72aa2aa2003-06-09 19:31:17 +000020
yaberauneyaef772532009-10-09 17:55:43 +000021int TST_TOTAL = 1;
iyermanoj72aa2aa2003-06-09 19:31:17 +000022
yaberauneyaef772532009-10-09 17:55:43 +000023#if INET6
24char *TCID = "sendfile6_server";
25#else
26char *TCID = "sendfile_server";
27#endif
iyermanoj72aa2aa2003-06-09 19:31:17 +000028
Wanlong Gao354ebb42012-12-07 10:10:04 +080029int main(int argc, char *argv[])
plars865695b2001-08-27 22:15:12 +000030{
yaberauneyaef772532009-10-09 17:55:43 +000031 sai_t sa, *ap;
32 sa_t from;
33 struct addrinfo *hp;
34 struct addrinfo hints;
35 int as, fd, gai, rc, s;
36 char *lp;
37 char *number;
Wanlong Gao354ebb42012-12-07 10:10:04 +080038 int pid, nbytes, flen, count;
yaberauneyaef772532009-10-09 17:55:43 +000039 char rbuf[PATH_MAX];
Wanlong Gao354ebb42012-12-07 10:10:04 +080040 int chunks = 0;
Garrett Cooper2c282152010-12-16 00:55:50 -080041 off_t *offset;
yaberauneyaef772532009-10-09 17:55:43 +000042 char nbuf[PATH_MAX];
43 int port;
plars865695b2001-08-27 22:15:12 +000044
yaberauneyaef772532009-10-09 17:55:43 +000045 if (argc != 3) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +010046 tst_brkm(TBROK, NULL, "usage: listen-address listen-port");
yaberauneyaef772532009-10-09 17:55:43 +000047 }
Garrett Cooper2c282152010-12-16 00:55:50 -080048
yaberauneyaef772532009-10-09 17:55:43 +000049 /* open socket */
50 if ((s = socket(AFI, SOCK_STREAM, 0)) < 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +010051 tst_brkm(TBROK, NULL, "socket error = %d\n", errno);
plars865695b2001-08-27 22:15:12 +000052 }
53
Wanlong Gao354ebb42012-12-07 10:10:04 +080054 signal(SIGCHLD, SIG_IGN); /* ignore signals from children */
plars865695b2001-08-27 22:15:12 +000055
yaberauneyaef772532009-10-09 17:55:43 +000056 memset(&hints, 0, sizeof(hints));
57 hints.ai_family = PFI;
58 if ((gai = getaddrinfo(argv[1], NULL, &hints, &hp)) != 0) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +010059 tst_brkm(TBROK, NULL, "getaddrinfo failed");
plars865695b2001-08-27 22:15:12 +000060 }
yaberauneyaef772532009-10-09 17:55:43 +000061 if (!hp || !hp->ai_addr || hp->ai_addr->sa_family != AFI) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +010062 tst_brkm(TBROK, NULL, "getaddrinfo failed");
yaberauneyaef772532009-10-09 17:55:43 +000063 }
plars865695b2001-08-27 22:15:12 +000064
yaberauneyaef772532009-10-09 17:55:43 +000065 /* server IP and port */
66 memcpy(&sa, hp->ai_addr, hp->ai_addrlen);
67 port = atoi(argv[2]);
68#if INET6
69 sa.sin6_port = htons(port);
70#else
71 sa.sin_port = htons(port);
72#endif
plars865695b2001-08-27 22:15:12 +000073
yaberauneyaef772532009-10-09 17:55:43 +000074 /* bind IP and port to socket */
Wanlong Gao354ebb42012-12-07 10:10:04 +080075 if (bind(s, (sa_t *) & sa, sizeof(sa)) < 0) {
yaberauneyaef772532009-10-09 17:55:43 +000076 tst_resm(TBROK, "bind error = %d\n", errno);
77 close(s);
78 tst_exit();
79 }
Garrett Cooper2c282152010-12-16 00:55:50 -080080
yaberauneyaef772532009-10-09 17:55:43 +000081 /* start to listen socket */
82 if (listen(s, LISTEN_BACKLOG) < 0) {
83 tst_resm(TBROK, "listen error = %d\n", errno);
84 close(s);
85 tst_exit();
86 }
87
yaberauneyaec789bc2009-12-22 02:35:51 +000088 socklen_t fromlen = sizeof(from);
yaberauneyaef772532009-10-09 17:55:43 +000089
90 /* process connections */
91 while (1) {
92
93 /* accept a connection from a client */
Garrett Cooper8fb1cdb2010-11-28 22:56:35 -080094 if ((as = accept(s, &from, &fromlen)) < 0) {
yaberauneyaef772532009-10-09 17:55:43 +000095 tst_resm(TBROK, "accept error = %d\n", errno);
96 if (errno == EINTR)
97 continue;
98 close(s);
99 tst_exit();
100 }
101
Wanlong Gao354ebb42012-12-07 10:10:04 +0800102 ap = (sai_t *) & from;
yaberauneyaef772532009-10-09 17:55:43 +0000103
104 /* create a process to manage the connection */
105 if ((pid = fork()) < 0) {
106 tst_resm(TBROK, "fork error = %d\n", errno);
107 close(as);
108 tst_exit();
109 }
110 if (pid > 0) { /* parent, go back to accept */
111 close(as);
112 continue;
113 }
114
115 /* child process to manage a connection */
Garrett Cooper2c282152010-12-16 00:55:50 -0800116
Wanlong Gao354ebb42012-12-07 10:10:04 +0800117 close(s); /* close service socket */
yaberauneyaef772532009-10-09 17:55:43 +0000118
119 /* get client request information */
120 if ((nbytes = read(as, rbuf, PATH_MAX)) <= 0) {
121 tst_resm(TBROK, "socket read error = %d\n", errno);
122 close(as);
123 tst_exit();
124 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 rbuf[nbytes] = '\0'; /* null terminate the info */
yaberauneyaef772532009-10-09 17:55:43 +0000126 lp = &rbuf[0];
127
128 /* start with file length, '=' will start the filename */
129 count = flen = 0;
130 number = &nbuf[0];
Wanlong Gao354ebb42012-12-07 10:10:04 +0800131 while (*lp != '=') { /* convert ascii to integer */
yaberauneyaef772532009-10-09 17:55:43 +0000132 nbuf[count] = *lp;
133 count++;
134 lp++;
135 }
136 nbuf[count] = '\0';
Cyril Hrubiscf0d6262014-09-23 14:03:31 +0200137 flen = strtol(number, NULL, 10);
yaberauneyaef772532009-10-09 17:55:43 +0000138
139 /* the file name */
140 lp++;
141
142 tst_resm(TINFO, "The file to send is %s\n", lp);
143 /* open requested file to send */
144 if ((fd = open(lp, O_RDONLY)) < 0) {
145 tst_resm(TBROK, "file open error = %d\n", errno);
146 close(as);
147 tst_exit();
148 }
149 offset = NULL;
150 errno = 0;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 do { /* send file parts until EOF */
yaberauneyaef772532009-10-09 17:55:43 +0000152 if ((rc = sendfile(as, fd, offset, flen)) != flen) {
153 if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800154 tst_resm(TBROK,
155 "sendfile error = %d, rc = %d\n",
156 errno, rc);
yaberauneyaef772532009-10-09 17:55:43 +0000157 close(as);
158 close(fd);
159 tst_exit();
160 }
161 }
162 chunks++;
163 } while (rc != 0);
164 tst_resm(TINFO, "File %s sent in %d parts\n", lp, chunks);
plars865695b2001-08-27 22:15:12 +0000165
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 close(as); /* close connection */
167 close(fd); /* close requested file */
plars865695b2001-08-27 22:15:12 +0000168
yaberauneyaef772532009-10-09 17:55:43 +0000169 exit(0);
170
171 }
172
Wanlong Gao354ebb42012-12-07 10:10:04 +0800173 close(s); /* close parent socket (never reached because of the while (1)) */
yaberauneyaef772532009-10-09 17:55:43 +0000174
Garrett Cooper2c282152010-12-16 00:55:50 -0800175 tst_exit();
yaberauneyaef772532009-10-09 17:55:43 +0000176
Chris Dearmanec6edca2012-10-17 19:54:01 -0700177}