I suggest overriding select function in module HTTP::Daemon::ClientConn.
The new select function checks args & if "our case" happens it calls IO::Socket::SSL::peek function instead of CORE::select.
I have tested the code on my server - it's works fine. Timeout in this implementation should work too. plz have a look at the patch:
diff -u orig/SSL.pm mod/SSL.pm
--- orig/SSL.pm 2008-02-12 03:27:03.000000000 +0200
+++ mod/SSL.pm 2009-05-05 17:38:50.000000000 +0300
@@ -69,6 +69,11 @@
use vars qw($VERSION @ISA $PROTO $DEBUG);
+BEGIN {
+no strict;
+*{"HTTP::Daemon::ClientConn::select"} = \&HTTP::Daemon::SSL::select;
+}
+
use IO::Socket::SSL;
use HTTP::Daemon;
@@ -93,6 +98,42 @@
=cut
+my %save_handlers;
+
+sub select($$$$)
+{
+ my ($r,$w,$e,$timeout) = @_;
+ unless (!defined($w) && !defined($e)) {
+ return CORE::select($r,$w,$e,$timeout);
+ }
+ # may be our case.
+ # detail check this:
+ my $value = vec($r,0,length($r)*8);
+ return CORE::select($r,$w,$e,$timeout) if ( ($value & ($value - 1)) or (!$value)) ; # must only one bit set (see HTTP::Daemon code)
+ my $fd;
+ for($fd=0;$fd < length($r)*8;$fd++) { last if (vec($r,$fd,1));};
+
+ die "bad thing happen ;-(" if ($fd == length($r)*8);
+ return CORE::select($r,$w,$e,$timeout) unless (defined($save_handlers{$fd}));
+
+ # ok. it's our case
+ my ($buf,$res);
+
+ { # set timeout of operation
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ alarm $timeout;
+ $res = $save_handlers{$fd}->peek($buf,1);
+ alarm 0;
+ }
+ if (!defined($res) or $res < 0) {
+ # error or timeout
+ # FIXME: timeout ???
+ return undef;
+ }
+ # $res >= 0)
+ return 1;
+}
+
sub new
{
my ($class, %args) = @_;
@@ -109,6 +150,7 @@
my ($sock, $peer) = IO::Socket::SSL::accept($self,$pkg);
if ($sock) {
${*$sock}{'httpd_daemon'} = $self;
+ $save_handlers{fileno($sock)} = $sock;
return wantarray ? ($sock, $peer) : $sock;
}
else {