testsf_s.c revision 07e8e2a8351e527485e381a996c025b5e3841897
1d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com/*
2d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com * Server for the sendfile test program
3d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com * Syntax: testsf_s <own IP addr>
4d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com */
5d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com
6d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com#include <stdio.h>
7d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com#include <stdlib.h>
8d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com#include <unistd.h>
9aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com#include <sys/file.h>
10901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips#include <errno.h>
11901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips#include <sys/signal.h>
12901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips#include <sys/types.h>
134a339529612a43871d021877e58698e067d6c4cdbsalomon#include <netinet/in.h>
1454f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman#include <sys/socket.h>
15587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
16587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon#define LISTEN_BACKLOG	10
17587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
18587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
19587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
2077af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comvoid *
210bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomontest_sig(sig)
22d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.comint sig;
23d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com{
244a339529612a43871d021877e58698e067d6c4cdbsalomon
2554f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman  int status;
26c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com
27587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  wait(&status);
28587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
29587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
30587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon}
31587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
32587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
3377af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.commain(argc, argv)
340bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomonint argc;
35d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.comchar *argv[];
36d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
374a339529612a43871d021877e58698e067d6c4cdbsalomon{
3854f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman  struct sockaddr_in sa, *ap;
39587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  struct sockaddr from;
40587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  int s, fd, as, rc;
41587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  char *lp;
42587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  char *number;
43587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  int i, clen, pid;
44587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  int flags, nonblocking;
4577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com  int nbytes, flen,count;
460bbecb21ab82b3d742c491780bcc2e74be03efedBrian Salomon  char rbuf[PATH_MAX];
471ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com  int chunks=0;
481ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com  off_t *offset;
49587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  char nbuf[PATH_MAX];
50587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  int port;
51901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips
52901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  /* open socket */
53587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
54587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon	printf("socket error = %d\n", errno);
55587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon	exit(-1);
56587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  }
57901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips
58901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  signal(SIGCHLD, SIG_IGN); /* ignore signals from children */
59901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips
60901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  /* server IP and port */
61587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  sa.sin_family = AF_INET;
62587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  sa.sin_addr.s_addr = inet_addr(argv[1]);
63901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  port=atoi(argv[2]);
64901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  sa.sin_port = htons(port);
65901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips
66587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  /* bind IP and port to socket */
67587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  if ( bind(s, (struct sockaddr*) &sa, sizeof(sa) ) < 0 ) {
68587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        printf("bind error = %d\n", errno);
69587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon	close(s);
70901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips	exit(-1);
71901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  }
72901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips
73901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  /* start to listen socket */
74587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  if ( listen(s, LISTEN_BACKLOG ) < 0 ) {
75587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        printf("listen error = %d\n", errno);
76901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips	close(s);
77587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon	exit(-1);
78587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  }
79587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
80587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  /* process connections */
81587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon  while(1) {
82901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips	/* accept a connection from a client */
83901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  	clen = sizeof(from);
84901f29ad3e38b7072a2abef5ff1665cd755d21a2Robert Phillips  	if ((as = accept(s, &from, &clen )) < 0 ) {
85	  printf("accept error = %d\n", errno);
86	  if (errno == EINTR)
87		continue;
88	  close(s);
89	  exit(-1);
90  	}
91
92	ap = (struct sockaddr_in *)&from;
93
94	/* create a process to manage the connection */
95	if ((pid = fork()) < 0) {
96	  printf("fork error = %d\n", errno);
97	  close(as);
98	  exit(-1);
99  	}
100	if (pid > 0) {	/* parent, go back to accept */
101	  close(as);
102	  continue;
103	}
104
105
106
107	/* child process to manage a connection */
108
109	close(s); /* close service socket */
110
111	/* get client request information */
112	if ((nbytes = read(as, rbuf, 80)) <= 0) {
113	  printf("socket read error = %d\n", errno);
114	  close(as);
115	  exit(-1);
116  	}
117	rbuf[nbytes] = '\0'; /* null terminate the info */
118	lp = &rbuf[0];
119
120	/* start with file length, '=' will start the filename */
121	flen = 0;
122	count = 0;
123	number = &nbuf[0];
124	while (*lp != '=') { /* convert ascii to integer */
125	  nbuf[count] = *lp;
126	  count++;
127	  lp++;
128	}
129	 nbuf[count] = '\0';
130	 flen = strtol(number, (char **)NULL, 10);
131
132	/* the file name */
133	lp++;
134
135        printf("The file to send is %s\n", lp);
136  	/* open requested file to send */
137	if ((fd = open(lp, O_RDONLY)) < 0) {
138	  printf("file open error = %d\n", errno);
139	  close(as);
140	  exit(-1);
141  	}
142	offset=NULL;
143	errno=0;
144        do { /* send file parts until EOF */
145           if ((rc = sendfile(as, fd, offset, flen)) != flen) {
146                if ((errno != EWOULDBLOCK) && (errno != EAGAIN)) {
147                        printf("sendfile error = %d, rc = %d\n", errno, rc);
148                        close(as);
149                        close(fd);
150                        exit(-1);
151                }
152          }
153	  chunks++;
154        } while (rc != 0);
155	printf("File %s sent in %d parts\n", lp, chunks);
156
157
158	close(as); /* close connection */
159	close(fd); /* close requested file */
160	exit(0);
161
162  }
163
164
165  close(s); /* close parent socket (never reached because of the while(1)) */
166
167
168
169
170}
171
172