Hi List.
I have a puzzling problem in a custom PerlAuthenHandler module.
I have checked the documentation, and the mod-perl mailing lists as far
as a year back without finding anything relevant.
I cannot believe something this simple and this big would not have been
found out yet by someone else, so I suppose there is a very stupid
mistake on my part, but for the life of me..
In summary, the problem is that in the authen module I open a tcp
connection to an external server *once*, but the server sees *two*
connections being opened.
I know the above because I trace what happens on both sides and that is
what the logfiles show.
If this rings a bell for anyone right now, you might not need to peruse
the rest, just give me a clue.
More in detail :
Environment :
Apache/2.2.3 (Debian) DAV/2 mod_jk/1.2.18 PHP/4.4.4-8+etch4
mod_ssl/2.2.3 OpenSSL/0.9.8c mod_perl/2.0.2 Perl/v5.8.8 Server at
xxx.com Port 80
Host uname -a :
Linux arthur 2.6.18-4-686 #1 SMP Wed May 9 23:03:12 UTC 2007 i686 GNU/Linux
My custom authen module is supposed to do user authentication versus a
proprietary database system. For that it open a TCP connection with the
database server, sends it some XML-formatted request, and reads the
answer to determine if the authentication worked or not.
I use the same database connection and verification code in a perl
cgi-bin script to the same effect, and it works fine there.
When using this same code in this new Apache2 module however, it looks
(from the external database server connection trace) as if the Apache2
module is opening the connection not once, but twice !
Then what seems to happen is that the message to the database is sent on
one of these sockets, but my module tries to read the answer on the
"other" (?) socket and gets stuck waiting for an answer that never comes
(because on the second connection, the database server never received
any request).
The code used to open the socket is the following; it is located in a
sub() used by the authentication module, and there is only one
place where this code is present, and is called.
my $XMLAddr = inet_aton($XMLHost); # XMLHost is "localhost"
my $Paddr = sockaddr_in($XMLPort, $XMLAddr); # XMLPort is "11100"
unless (socket(XMLSRV, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
&& connect(XMLSRV, $Paddr)) {
$r->warn("$$: ** Cannot connect to Star XML server **");
return 0;
}
XMLSRV->autoflush(1);
binmode(XMLSRV);
$r->warn("$$: Connected to StarXML.");
According to the Apache server log, the above code is executed once, not
twice.
But according to the target database system log, 2 separate tcp
connections are being opened !
Next, I send the XML message on the same handle via
$xmlout = "<tag>some message</tag>";
unless (defined($xmlsize = send(XMLSRV,$xmlout,0))) {
$r->warn(" ** Star XML request not sent : $! **");
close XMLSRV;
return 0;
}
The Apache logfile shows the message sent once, correctly.
The database server log shows the message being received on one of the
now open connections (unfortunately, it doesn't say which).
Then I try to read the response, via
[...]
$xmlread = recv(XMLSRV,$xmlbuf,4096,0); # read header
And that is where I get stuck, waiting forever on the recv(), although
the database server log shows the response being sent (but unfortunately
not on which connection it is being sent).
I have tried various methods to open the socket and write/read to/from
it (IO::Socket::INET, syswrite, sysread, read, etc..) but nothing seems
to make a difference. There are always 2 connections on the database
server side, for a single new() or open() or connect() on the Apache
side, and it always gets stuck on the read() or recv(). I have also
inserted a tunnel-like tracing module (similar to socat) between the
authentication module and the database system, which confirms that my
apache module is effectively opening 2 connections instead of one. I'm
puzzled.
The Apache configuration for the authentication is as follows :
<Location "/priv">
#SetHandler perl-script
PerlAuthenHandler AM::Authtest
AuthType Basic
AuthName "Protected Area"
Require valid-user
PerlSetVar DebugLevel 1
PerlSetVar ClientCode "SKA"
PerlSetVar CookieName 'JoeSkasCookie'
PerlSetVar LogMethod "STARLOGXML"
PerlSetVar LogStarXMLHost "arthur:11300"
PerlSetVar LogStarHost "arthur:11002"
PerlSetVar LogStarDB "STARLOG"
</Location>
Before I send more info or source code, does this ring a bell for anyone
? Am I overlooking something evident or some Apache/mod_perl
particularity regarding sockets ?
Thank you in advance,
aw