#!/usr/bin/perl -w use IO::Socket; autoflush STDOUT 1; autoflush STDERR 2; sub compare_arrays { my ($first, $second) = @_; no warnings; # silence spurious -w undef complaints return 0 unless @$first == @$second; for (my $i = 0; $i < @$first; $i++) { return 0 if $first->[$i] ne $second->[$i]; } return 1; } sub handlerequest() { getrequest(); } sub getrequest() { $port = 80; while($reqline = <$client>) { chop $reqline; chop $reqline; unless ($reqline =~ /^Proxy-Connection:.*$/) { push(@request, $reqline); } if ($reqline =~ /^Host: (.*)$/) { $prehost = $1; if ($prehost =~ /^(.*):(.*)$/) { $host = $1; $port = $2; } else { $host = $prehost; } } if ( $reqline eq "" ) { foreach $line (@request) { print("$$ --> $host: $line\n"); } print("\n"); getresponse(); close($client) and exit; @request = (); } } } sub getresponse() { $webserver = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => "tcp", Type => SOCK_STREAM) or warn("Could not contact $host\n") and close($client) and return; print("\tnew webserver connection $$\n"); foreach $line (@request) { print($webserver "$line\n"); } $inheader = 1; while ($inheader) { $respline = <$webserver>; while (substr($respline, -1) eq "\n" or substr($respline, -1) eq "\r") { chop($respline); } if ($respline =~ /^Content-Length: (.*)$/) { $contentlength = $1; } print($client "$respline\n") or die("Client already closed? $!"); if ($respline eq "") { $inheader = 0; print("\t <-- $$ $host: (data follows)\n") or die("Client already closed? $!"); } else { print("\t <-- $$ $host: $respline\n") or die("Client already closed? $!"); } } if (defined($contentlength)) { read($webserver, $serverchar, $contentlength) && print("\t <-- $$ $host: (read $contentlength bytes, as specified)\n"); # What happens if there's a short read()? Hmmm... print($client $serverchar) or die("Client already closed? $!"); close($webserver); } else { while (read $webserver, $serverchar, 1) { $contentlength += 1; print($client $serverchar); } defined($contentlength) && print("\t <-- $$ $host: (read $contentlength bytes, counted)\n"); } print("\t$host closed connection $$.\n\n"); } $proxy_port = 8000; $proxy = IO::Socket::INET->new(LocalPort => $proxy_port, Type => SOCK_STREAM, Reuse => 1, Listen => 10 ) # or SOMAXCONN or die "Couldn't bind to port $proxy_port : $@\n"; while ($client = $proxy->accept()) { # $client is the new connection $pid = fork; if ($pid == 0) { close($proxy); handlerequest(); } else { close($client); #wait; } } close($proxy);