>> If it's the latter, we can defer calling it until select() says there's
>> data ready.  TIEHANDLE can do everything up to the accept() call, then
>> we can wait for the client to send something before accepting the
>> connection.
>
> Not sure but maybe we could select and peek until we got 11 bytes and
> then pass it on to SSL_accept?

Maybe something like this, just a hack which unfortunately spins
because I do not know how to tell POE not to call READ again after I
have PEEK'ed at the socket... 

--- SslServer.pm.orig   Thu Jan 15 11:12:43 2004
+++ SslServer.pm        Thu Jan 15 15:22:10 2004
@@ -18,8 +18,6 @@
 use Net::SSLeay qw(die_if_ssl_error);
 use POSIX qw(F_GETFL F_SETFL O_NONBLOCK EAGAIN EWOULDBLOCK);
 
-sub TIMEOUT () { 5 }
-
 sub TIEHANDLE {
   my ($class, $socket, $key, $cert) = @_;
 
@@ -53,22 +51,7 @@
                                    );
   die_if_ssl_error("certificate");
 
-  eval {
-    local $SIG{ALRM} = sub { die "alarm\n" };
-    alarm TIMEOUT;
-    my $resp = Net::SSLeay::accept($ssl);
-    alarm 0;
-    if ($resp == -1) {
-      # handshake could not complete
-      die ("handshake failed");
-    }
-  };
-  if ($@) {
-    die unless $@ eq "alarm\n";
-    # timed out
-    die("SSL handshake timed out, maybe increase timeout in SslServer.pm");
-  }
-
+  # delay accept() until we have atleast 11 bytes on socket
   $class->_set_filenum_obj($fileno, $ssl, $ctx, $socket);
 
   return bless $socket, $class;


--- SslClient.pm.orig   Thu Jan 15 11:12:36 2004
+++ SslClient.pm        Thu Jan 15 15:20:19 2004
@@ -14,6 +14,8 @@
 use vars qw(@ISA);
 @ISA = qw(Net::SSLeay::Handle);
 
+sub SIZE_SSL23_HANDSHAKE () { 11 }
+
 my %Filenum_Object;
 
 sub _get_self {
@@ -25,6 +27,26 @@
   return $Filenum_Object{fileno($socket)}->{ssl};
 }
 
+sub _is_server_side {
+  my $socket = shift;
+  return exists $Filenum_Object{fileno($socket)}->{accepted} ? 1 : 0;
+}
+
+sub _is_accepted {
+  my $socket = shift;
+  return $Filenum_Object{fileno($socket)}->{accepted} ? 1 : 0;
+}
+
+sub _accepted {
+  my $socket = shift;
+  $Filenum_Object{fileno($socket)}->{accepted} = 1;
+}
+
+sub _get_filenum_obj {
+  my $socket = shift;
+  return $Filenum_Object{fileno($socket)};
+}
+
 sub _set_filenum_obj {
   my ($self, $fileno, $ssl, $ctx, $socket) = @_;
   $Filenum_Object{$fileno} =
@@ -32,6 +54,9 @@
     ctx    => $ctx,
     socket => $socket,
     fileno => $fileno,
+    accepted => 0,
+    readfdset => undef,
+    accept_buffer => '',
   };
 }
 
@@ -71,6 +96,41 @@
   my ($socket, $buf, $len, $offset) = \ (@_);
   my $ssl = $$socket->_get_ssl();
 
+  if ($$socket->_is_server_side() && !$$socket->_is_accepted()) {
+    my $filenum_obj = $$socket->_get_filenum_obj();
+    if (!defined($filenum_obj->{readfdset})) {
+      vec($filenum_obj->{readfdset}, $filenum_obj->{fileno}, 1) = 1;
+    }
+    my $accept_buffer = $filenum_obj->{accept_buffer};
+    while (select($filenum_obj->{readfdset}, undef, undef, undef)) {
+      if (!vec($filenum_obj->{readfdset}, $filenum_obj->{fileno}, 1)) {
+       return;
+      }
+      my $ret = recv($filenum_obj->{socket}, $_,
+                    SIZE_SSL23_HANDSHAKE , Socket::MSG_PEEK);
+      if (!defined($ret)) { # undef mean error
+       return;
+      }
+      if (length($accept_buffer) == length($_)) {
+       # nothing new, here we would like to make POE not call us again
+       # until new data has arrived.. XXX
+        return length($_);
+      }
+      $accept_buffer = $_;
+      if (length($accept_buffer) == SIZE_SSL23_HANDSHAKE ) {
+       my $resp = Net::SSLeay::accept($ssl);
+       if ($resp == -1) {
+         # handshake could not complete
+         die ("handshake failed");
+       }
+       $$socket->_accepted();
+       goto GO_ON;
+      }
+    }
+    return;
+  }
+
+ GO_ON:
   # No offset.  Replace the buffer.
   unless (defined $$offset) {
     $$buf = Net::SSLeay::read($ssl, $$len);

Reply via email to