#!/usr/bin/perl -w # sanada4.pl - Don Yang (uguu.org) # # 11/26/03 use Socket; sub T { print "$$: ", (scalar(localtime)), ": @_\n"; } die "$0 [port] [type]\n" unless( $#ARGV > -1 ); ($n, $p, $t) = @ARGV; die "$n is empty\n" unless( (-f $n) && ($s = -s $n) > 0 ); $p ||= 80; $t ||= "application/octet-stream"; $e = "\r\n"; $h = "Server: Sanada-san$e" . "Accept-Ranges: bytes$e" . "Content-Type: $t$e" . "Connection: close$e$e"; $SIG{"CHLD"} = "IGNORE"; die "$!\n" unless( socket(S, PF_INET, SOCK_STREAM, getprotobyname("tcp")) && bind(S, sockaddr_in($p, INADDR_ANY)) && listen(S, 5) && binmode(S)); $x = ""; vec($x, fileno(S), 1) = 1; T("serving $n (type=$t, size=$s) on port $p"); while( select($o = $x, undef, undef, undef) ) { if( vec($o, fileno(S), 1) ) { $j = accept(C, S); ($j, $i) = sockaddr_in($j); $i = inet_ntoa($i); if( fork ) { close(C); } else { T("request from $i:$j"); binmode(C); defined(recv(C, $x, 1024, 0)) || die $!; T("agent=$1") if( $x =~ /\s+user-agent:\s*([^\r\n]+)/i ); T("referer=$1") if( $x =~ /\s+referer:\s*([^\r\n]+)/i ); $j = $s - 1; ($i, $j) = ($x =~ /\s+range:\s*bytes=(\d+)-(\d+)/i) ? ($1, $2) : ($x =~ /\s+range:\s*bytes=(\d+)-/i) ? ($1, $j) : ($x =~ /\s+range:\s*bytes=-(\d+)/i) ? ($s - $1, $j) : (0, $j); $o = ( ($i >= $s || $j >= $s || $j < $i) ? "HTTP/1.1 416 Requested Range Not Satisfiable$e" . "Content-Range: bytes */$s$e" : ( ($i > 0 || $j < $s - 1) ? "HTTP/1.1 206 Partial Content$e" . "Content-Range: bytes $i-$j/$s$e" : "HTTP/1.1 200 OK$e" ) . "Content-Length: " . ($j - $i + 1) . $e ) . $h; send(C, $o, 0) || die $!; if( ($o =~ /1\.1 20/) && ($x =~ /^GET /) ) { open(D, "< $n"); $j++; for(seek(D, $i, $t = 0); $i < $j; $i += $p) { if(($p = $j - $i) > 0x4000) {$p = 0x4000;} read(D, $o, $p); last unless defined(send(C, $o, 0)); $t += $p; } close(D); if($i < $j) {$t = "~$t";} T("sent $t bytes"); } shutdown(C, 2); close(C); exit(0); } } } die "$!\n";