package Handoff; use strict; use warnings; use Apache2::RequestRec (); use Apache2::RequestIO (); use Apache2::Const -compile => qw(:common :conn_keepalive :http); use File::FDpasser; use POSIX; # 1. subserver creates a named socket (/tmp/handoff) and listens on it # 2. browser connects to apache (thus creating client-socket) makes a request # 3. Apache looks at the request, and decides that it should go to # mod_handoff # 4. mod_handoff connects to the subserver using the /tmp/handoff and # creates a pipe-type socket (ipc-pipe). It sends client-socket to # the subserver over ipc-pipe, closes client-socket, sends the request # over ipc-pipe, and then logs the result. Note that client-socket # only is closed from apache... it's still open in the subserver. # # 5. The subserver reads the request on ipc-pipe, and responds over # client-socket. # # 6. If mod_handoff cannot open the fs-based socket, then it returns an # error code of some kind to the client. sub handler { my ($r) = @_; my $fh = endp_connect("/tmp/handoff"); if (not $fh) { $r->warn("could not connect to handoff endpoint"); return &Apache2::Const::HTTP_SERVICE_UNAVAILABLE; } # This only works with the prefork MPM, I think. my $client = 0; my $rc = send_file($fh,$client); # To prevent Apache from writing to the socket (which we have handed # off to another process), replace the client socket with /dev/null POSIX::dup2(POSIX::open("/dev/null", &POSIX::O_RDWR), $client); # send the request to the subserver print $fh $r->the_request."\r\n"; # send the headers too $r->headers_in->do(sub { my ($k, $v)=@_; print $fh "$k: $v\r\n"; } ); close $fh; # do whatever we can to prevent apache from using the client socket again $r->assbackwards(1); $r->connection->keepalive(&Apache2::Const::CONN_CLOSE); return &Apache2::Const::DONE; } 1;