26 #include <sys/socket.h>
31 #include <sys/resource.h>
34 #include <sys/types.h>
37 #include <sys/filio.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
45 #include <sys/ioctl.h>
58 typedef unsigned char BYTE;
61 #define BUFFERBLOCKSIZE 8192U
64 #define CTRL_BEGINRUN 1
68 #define CTRL_SENDFILENAME 5
69 #define CTRL_ROLLOVER 6
71 #define CTRL_REMOTESUCCESS 100
72 #define CTRL_REMOTEFAIL 101
74 #define ROLE_RECEIVED 0
75 #define ROLE_WRITTEN 1
80 #define INITIAL_SIZE (4*1024*1024)
117 int readn(
int ,
char *,
int);
118 int writen(
int ,
char *,
int);
120 #if defined(SunOS) || defined(Linux)
130 void cleanup(
const int exitstatus);
142 cout <<
"** This is the Super Fast Server :-)." << endl;
143 cout <<
"** usage: sfs " << endl;
144 cout <<
" -d disable database logging [ db not yet implemented ]" << endl;
145 cout <<
" -b interface bind only to this interface" << endl;
146 cout <<
" -p number use this port (default 5001)" << endl;
147 cout <<
" -v increase verbosity" << endl;
148 cout <<
" -x do not write data to disk (testing)" << endl;
149 cout <<
" Examples:" << endl;
150 cout <<
" sfs -b ens801f0 -- listen only on that interface" << endl;
151 cout <<
" sfs -p 5002 -- listen on port 5002" << endl;
167 int main(
int argc,
char* argv[])
171 #if defined(SunOS) || defined(Linux)
172 struct sockaddr client_addr;
174 struct sockaddr_in client_addr;
176 struct sockaddr_in server_addr;
179 int client_addr_len =
sizeof(client_addr);
181 unsigned int client_addr_len =
sizeof(client_addr);
184 pthread_mutex_init(&
M_cout, 0);
185 pthread_mutex_init(&
M_write, 0);
186 pthread_mutex_init(&
M_done, 0);
191 in_addr_t listen_address = htonl(INADDR_ANY);
195 while ((c = getopt(argc, argv,
"hvdxb:p:")) != EOF)
234 sscanf (argv[optind],
"%d", &
the_port);
240 if ( (
sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
247 int s = setsockopt(
sockfd, SOL_SOCKET, SO_RCVBUF,
252 perror(
"Setsockopt:");
255 memset( &server_addr, 0,
sizeof(server_addr));
256 server_addr.sin_family = AF_INET;
257 server_addr.sin_addr.s_addr = listen_address;
258 server_addr.sin_port = htons(
the_port);
262 if ( ( i = bind(
sockfd, (
struct sockaddr*) &server_addr,
sizeof(server_addr))) < 0 )
268 if ( ( i = listen(
sockfd, 100) ) )
276 cout <<
" listening on port " <<
the_port;
284 struct sockaddr_in out;
291 client_addr_len =
sizeof(
out);
292 dd_fd = accept(
sockfd, (
struct sockaddr *) &out, &client_addr_len);
295 pthread_mutex_lock(&
M_cout);
296 cout <<
"error in accept socket" << endl;
297 pthread_mutex_unlock(&
M_cout);
305 getnameinfo((
struct sockaddr *) &out,
sizeof(
struct sockaddr_in), h, 511,
311 cout <<
" new connection from " << host <<
" at " <<
time(0) << endl;
315 if ( (pid = fork()) == 0 )
337 bf_being_received = &B0;
338 bf_being_written = &B1;
361 cout <<
"error in thread create " << i << endl;
373 i = ioctl (
dd_fd, FIONBIO, 0);
384 if ( (status =
readn (
dd_fd, (
char *) &xx,
sizeof(xx)) ) <= 0)
386 cout <<
"error in read from socket" << endl;
391 controlword = ntohl(xx);
451 output_fd =
open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_LARGEFILE ,
452 S_IRWXU | S_IROTH | S_IRGRP );
455 cerr <<
"file " << filename <<
" exists, I will not overwrite " << endl;
462 cout <<
" opened new rollover file " << filename << endl;
473 readn (
dd_fd, (
char *) &local_runnr,
sizeof(local_runnr) );
474 local_runnr = ntohl(local_runnr);
479 output_fd =
open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_LARGEFILE ,
480 S_IRWXU | S_IROTH | S_IRGRP );
483 cerr <<
"file " << filename <<
" exists, I will not overwrite " << endl;
490 cout <<
" opened new file " << filename << endl;
494 bf_being_received = &B0;
495 bf_being_written = &B1;
498 bf_being_received->
dirty=0;
501 bf_being_written->
dirty = 0;
514 status =
readn (
dd_fd, (
char *) &len,
sizeof(i));
519 if ( (len+
sizeof(
int)-1)/
sizeof(
int) > bf_being_received->
buffersize)
521 delete [] bf_being_received->
bf;
522 bf_being_received->
buffersize = (len +
sizeof(int)-1)/
sizeof(int) + 2048;
524 pthread_mutex_lock(&
M_cout);
526 pthread_mutex_unlock(&
M_cout);
531 p = (
char *) bf_being_received->
bf;
536 pthread_mutex_lock(&
M_cout);
540 pthread_mutex_unlock(&
M_cout);
545 bf_being_received->
dirty = 1;
548 pthread_mutex_lock(&
M_done);
552 bf_being_written = bf_temp;
557 pthread_mutex_unlock(&
M_write);
567 pthread_mutex_lock(&
M_done);
573 cout <<
" closed file " << filename <<
" at " <<
time(0) << endl;
579 pthread_mutex_unlock(&
M_done);
590 cout <<
" closed connection from " << host << endl;
594 cout <<
" closed connection from " << host <<
" at " <<
time(0) << endl;
602 if (
verbose > 1) cout <<
" ending thread " <<
" at " <<
time(0) << endl;
619 pthread_mutex_lock(&
M_cout);
621 pthread_mutex_unlock(&
M_cout);
626 pthread_mutex_lock(&
M_cout);
628 pthread_mutex_unlock(&
M_cout);
631 if ( bytes != bytecount)
633 pthread_mutex_lock(&
M_cout);
634 cout << __LINE__ <<
" " << __FILE__ <<
" write error " << bytes <<
" " << bytecount << endl;
635 pthread_mutex_unlock(&
M_cout);
636 bf_being_written->
dirty = -1;
641 bf_being_written->
dirty = 0;
646 bf_being_written->
dirty = 0;
648 pthread_mutex_unlock(&
M_done);
665 nread =
read (fd, ptr, nleft);
671 #ifdef FRAGMENTMONITORING
672 history[hpos++] = nread;
678 #ifdef FRAGMENTMONITORING
681 cout <<
"Fragmented transfer of " << nbytes <<
"bytes: ";
682 for (
int i=0;
i<hpos;
i++)
684 cout <<
" " << history[
i]<<
",";
689 return (nbytes-nleft);
698 nwritten =
write (fd, ptr, nleft);
705 return (nbytes-nleft);
715 if ( strlen(interface) >= IFNAMSIZ)
717 cerr <<
" Interface name too long, ignoring "<< endl;
718 return htonl(INADDR_ANY);
721 fd = socket(AF_INET, SOCK_DGRAM, 0);
724 ifr.ifr_addr.sa_family = AF_INET;
727 strncpy(ifr.ifr_name, interface, IFNAMSIZ-1);
729 ioctl(fd, SIOCGIFADDR, &ifr);
732 in_addr_t
a = ((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
734 if (
verbose) cout <<
" binding to address " << inet_ntoa( ((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr ) << endl;