I have two questions regarding how to use Net::SSLeay::read.
--------------------------------- QUESTION #1 ---------------------------------
My first question regards the usage of Net::SSLeay::get_error.
I see in the man pages for the C functions SSL_read() and SSL_get_error() that,
in order to determine the case of a failure of SSL_read(), you call
SSL_get_error(). The return value of SSL_read() is passed as a parameter to
SSL_get_error():
SSL* ssl; void* buf; int num; int ret; int err; ret = SSL_read(ssl,buf,num); if(ret<0) err = SSL_get_error(ssl,ret);
Net::SSLeay's wrapper of SSL_get_error() looks just like the C function. Its
usage is:
$err = Net::SSLeay::get_error($ssl,$ret);
However, Net::SSLeay's wrapper of the SSL_read() looks a little different from
the C function. Its usage is:
$got = Net::SSLeay::read($ssl);
If the read is successful, Net::SSLeay::read returns the data that is read; if
the connection has been closed, it returns the empty string; if an error
occurs, it returns undef.
So, if SSL_read() fails and returns a negative value, that value is not
returned by Net::SSLeay::read. I need to pass this value as the second
parameter to Net::SSLeay::get_error, but I don't have it. So how do I identify
the specific error that occured?
[Note: the thread's error queue doesn't seem to have anything. In my code,
Net::SSLeay::ERR_peek_error returns 0 after Net::SSLeay::read returns undef.
However, in C code, I find that SSL_get_error() can identify the error although
ERR_peek_error returns 0.]
--------------------------------- QUESTION #2 ---------------------------------
My second question regards how to determine when an SSL connection, based on a
non-blocking socket, is ready for reading. I wrote the following code:
# $select_set is a select set for the socket underlying my SSL connection.
while (1) {
my $rset = $select_set;
select $rset,undef,undef,undef;
while (1) {
my $got = Net::SSLeay::read($ssl);
if (!defined $got) {
last;
}
if ($got eq "") {
print "socket closed\n";
Net::SSLeay::free($ssl);
return;
}
print "Got this: [$got]\n";
}
}
This seems to work, but given my understanding of SSL, I suspect that there may
be a flaw here. I understand that, because of renegotiation or whatever, it is
sometimes necessary for the SSL library to write to the socket in order to
complete a requested read operation. So I suspect that my code is susceptible
to the following condition:
In a call to Net::SSLeay::read, a write is necessary. However, the socket is
not immediately available for writing, and it is non-blocking, so
Net::SSLeay::read fails. Execution returns to the select statement. The
select is waiting for the socket to be ready for reading, but whoever is on the
other end of the connection isn't sending any data because he's waiting for my
system to write whatever it was trying to write, so my process just sits there
in the select statement, waiting for the wrong thing, and waiting, and
waiting...
So, is it sometimes necessary to select for write-availability of the socket?
And under what condition is that? I tried the following:
my $rset = $select_set; my $wset = Net::SSLeay::want_write($ssl) ? $select_set : undef; select $rset,$wset,undef,undef;
However, with this code, it gets into state in which want_write is consistently
returning true although the socket is available for writing, so select returns
immediately, and the process spins through this loop very rapidly, consuming
all available CPU cycles.
What am I supposed to do here? Is the original version of the code actually
correct, and not susceptible to my imagined flaw? If not, what is the
correction? One possibility that has occurred to me is to pass a timeout to
select, so execution will return from select and call read periodically, "just
in case." That strikes me as unaesthetic, but I guess it's a possibility, if
there isn't a more elegant "correct" solution.
______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED]