views:

46

answers:

4

Hello,

I wonder if and how it is possible to write a custom "protocol handler" (listening at a custom port) for Apache 2 in PHP?

In C and mod_perl you can write so-called "protocol handlers", which intercept the early Apache stage (after a client socket connection has been accept()ed, but before any content has been written to it) and can for example handle FTP or SMTP protocols. Is it possible in PHP as well?

For example, I have the following simple mod_perl handler, which I'd like to port to PHP (to compare the memory usage - since my mod_perl-handler needs 20m per child). My handler listens at the port 843 and writes the string POLICY to the client socket:

package SocketPolicy;

# Run: semanage port -a -t http_port_t -p tcp 843
# And add following lines to the httpd.conf
# Listen 843
# <VirtualHost _default_:843>
#       PerlModule                   SocketPolicy
#       PerlProcessConnectionHandler SocketPolicy
# </VirtualHost>

use strict;
use warnings FATAL => 'all';
use APR::Const(-compile => 'SO_NONBLOCK');
use APR::Socket();
use Apache2::ServerRec();
use Apache2::Connection();
use Apache2::Const(-compile => qw(OK DECLINED));

use constant POLICY =>
qq{<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"&gt;
<cross-domain-policy>
<allow-access-from domain="*" to-ports="8080"/>
</cross-domain-policy>
\0};

sub handler {
        my $conn   = shift;
        my $socket = $conn->client_socket();
        my $offset = 0;

        # set the socket to the blocking mode
        $socket->opt_set(APR::Const::SO_NONBLOCK => 0);

        do {
                my $nbytes = $socket->send(substr(POLICY, $offset),
                             length(POLICY) - $offset);
                # client connection closed or interrupted
                return Apache2::Const::DECLINED unless $nbytes;
                $offset += $nbytes;
        } while ($offset < length(POLICY));

        my $slog = $conn->base_server()->log();
        $slog->warn('served socket policy to: ', $conn->remote_ip());
        return Apache2::Const::OK;
}

1;

Thanks, Alex

A: 

Technically yes you can with the socket extension given that you also allow you script to run long enough. By default a PHP script will be terminated after 60 sec or so.

So the main issue is to keep your PHP script running like a daemon.

Wernight
Ok, you suggest a hack: writing a PHP script which would be run by Apache 2 (but when?) and which would bind a socket listening at port 843. I'm not sure this will work and I'm looking for something else: in C and mod_perl you can write Apache "protocol handlers" (for example to handle FTP or SMTP). And my question is: if you can do it in PHP as well?
Alexander Farber
I never said that it should be run by Apache. You should probably run it from the shell.
Wernight
Ok, I will edit my question to make it more clear
Alexander Farber
A: 

It's perfectly possible.... there's even a full web server written in PHP

Mark Baker
Yes, but it is not an Apache 2 module. The nanoweb is a daemon written in PHP. I'm however asking, how to write an Apache 2 handler which would handle not the usual content generation stage, but a protocol stage like mod_ftp ( http://httpd.apache.org/mod_ftp/ ) does and which would listen at port 843.
Alexander Farber
A: 

No, mod_php doesn't implement the Apache handler phases that mod_perl does.

See http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/sapi/apache2handler/php_functions.c?revision=296107&amp;view=markup#l516

ptomli
A: 

Yes and no.... PHP has an Apache interface which uses the Apache handler API, as well as other interfaces, such as CLI, CGI etc. The PHP Apache API integration chooses not to expose the lower-level handling details like mod_perl does, so if you need access to these callbacks you'll have to write your own PHP Apache handler API implementation.

Robin
I still like how PHP offers persistent database connections and sockets - with mod_perl or C you need more work to implement them.
Alexander Farber