25.2.2.2.1. Socket-based protocol module

To demonstrate the workings of a protocol module, we'll
take a look at the Book::Eliza module, which sends
the data read from the client as input to
Chatbot::Eliza, which in turn implements a mock
Rogerian psychotherapist and forwards the response from the
psychotherapist back to the client. In this module we will use the
implementation that works directly with the connection socket and
therefore bypasses any connection filters.

A protocol handler is configured using the
PerlProcessConnectionHandler directive, and we
will use the Listen and
<VirtualHost> directives to bind to the
nonstandard port 8084:

panic% telnet localhost 8084
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
Escape character is '^]'.
Hello Eliza
How do you do. Please state your problem.
How are you?
Oh, I?
Why do I have core dumped?
You say Why do you have core dumped?
I feel like writing some tests today, you?
I'm not sure I understand you fully.
Good bye, Eliza
Does talking about this bother you?
Connection closed by foreign host.

The example handler starts with the standard package declaration and,
of course, usestrict;. As with
all Perl*Handlers, the subroutine name defaults to
handler. However, in the case of a protocol
handler, the first argument is not a request_rec,
but a conn_rec blessed into the
Apache::Connection class. We have direct access to
the client socket via
Apache::Connection's
client_socket( ) method, which returns an object
blessed into the APR::Socket class.

Inside the read/send loop, the handler attempts to read
BUFF_LEN bytes from the client socket into the
$buff buffer. The $rlen
parameter will be set to the number of bytes actually read. The
APR::Socket::recv( ) method returns an APR status
value, but we need only check the read length to break out of the
loop if it is less than or equal to 0 bytes. The handler also breaks
the loop after processing an input including the
"good bye" string.

Otherwise, if the handler receives some data, it sends this data to
the $eliza object (which represents the
psychotherapist), whose returned text is then sent back to the client
with the APR::Socket::send( ) method. When the
read/print loop is finished the handler returns
Apache::OK, telling Apache to terminate the
connection. As mentioned earlier, since this handler is working
directly with the connection socket, no filters can be applied.