chunkedserver (2468B)
1 #!/usr/bin/perl 2 3 use strict; 4 use Socket; 5 use POSIX; 6 7 # Verbose messaging 8 sub msg { 9 print STDERR ("chunkedserver: ", @_); 10 } 11 12 # Child process catcher 13 sub reaper { 14 while ((my $waitedpid = waitpid(-1,WNOHANG)) > 0) { 15 msg ("Child $waitedpid done", 16 ($? ? " with exit $?" : ''), 17 "\n"); 18 } 19 $SIG{CHLD} = \&reaper; 20 } 21 22 # Connection handler 23 sub handleconnection () { 24 my $pid; 25 26 # Daemonize 27 if (!defined ($pid = fork())) { 28 msg ("Can't fork: $!\n"); 29 return; 30 } elsif ($pid) { 31 # Parent branch 32 msg ("Connection handler started as pid $pid\n"); 33 return; 34 } 35 36 # Child branch 37 while (defined (my $line = <Client>)) { 38 chomp ($line); 39 $line =~ s/\r//; 40 last if ($line eq ''); 41 msg ("Client says: [$line]\n"); 42 } 43 44 msg ("Sending response\n"); 45 print Client ("HTTP/1.1 200 OK\r\n", 46 "Connection: close\r\n", 47 "Transfer-Encoding: chunked\r\n", 48 "Content-Type: text/plain\r\n", 49 "\r\n", 50 "5\r\n", 51 "Hello\r\n", 52 "1\r\n", 53 " \r\n", 54 "5\r\n", 55 "World\r\n", 56 "2\r\n", 57 "!\n\r\n", 58 "0\r\n", 59 "\r\n"); 60 exit (0); 61 } 62 63 # Daemon server 64 sub serve ($) { 65 my $port = shift; 66 67 # Create the tcp service. 68 socket (Server, PF_INET, SOCK_STREAM, getprotobyname ('tcp')) 69 or die ("Can't create chunkedserver socket: $!\n"); 70 setsockopt (Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) 71 or die ("Can't set socket options: $!\n"); 72 bind (Server, sockaddr_in ($port, INADDR_ANY)) 73 or die ("Can't bind to port: $!\n"); 74 listen (Server, SOMAXCONN) 75 or die ("Can't listen to socket: $!\n"); 76 msg ("Chunkedserver started on port $port.\n"); 77 78 $SIG{CHLD} = \&reaper; 79 $SIG{INT} = sub { 80 msg ("Interrupt caught, terminating..\n"); 81 exit(0); 82 }; 83 84 while (1) { 85 for (my $waitedpid = 0; 86 (my $paddr = accept (Client, Server)) || $waitedpid; 87 $waitedpid = 0, close (Client)) { 88 next if ($waitedpid and not $paddr); 89 my ($port, $iaddr) = sockaddr_in ($paddr); 90 my $name = gethostbyaddr ($iaddr, AF_INET); 91 92 msg ("Connection from $name/", inet_ntoa ($iaddr), ":$port\n"); 93 94 handleconnection (); 95 } 96 } 97 } 98 99 # Main starts here 100 if ($#ARGV != 1) { 101 die <<"ENDUSAGE"; 102 103 Usage: chunkedserver nsec portnr 104 105 ENDUSAGE 106 } 107 108 alarm (shift (@ARGV)); 109 serve (shift (@ARGV)); 110