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