Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this SSL_pending call always return zero?

This code is for an HTTPS server using blocking sockets:

  request := '';
  start := gettickcount;
  repeat
    if SSL_pending(ssl) > 0 then
      begin
      bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
      if bytesin > 0 then
        begin
        buffer[bytesin] := #0;
        request := request + buffer;
        end
      else break; // read failed
      end; // pending
   until (gettickcount - start) > LARGETIMEOUT;
   // "request" is ready, though possibly empty

SSL_pending() always returns zero and the SSL_read() is never reached. If the SSL_pending() call is removed, SSL_read() is executed. Why doesn't SSL_pending() indicate how many bytes are available?

Note that if you call SSL_read() and the number of bytes returned is less than your buffer size, you've read everything and are done.

If the incoming data is larger than your buffer size, the first SSL_read() call fills the buffer, and you can repeat calling SSL_read() until you can't fill the buffer.

BUT if the incoming data is an exact multiple of your buffer size, the last chunk of data fills the buffer. If you attempt another SSL_read() thinking there might be more data on a blocking socket, it hangs indefinitely. Hence the desire to check SSL_pending() first. Yet that doesn't appear to work.

How do you avoid hanging on a final SSL_read()? (I can't imagine the answer is to go non-blocking, since that means you could never use SSL_read with blocking.)

UPDATE: The following works. Apparently SSL_pending() doesn't work until after the first SSL_read():

  request := '';
  repeat
    bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
    if bytesin > 0 then
      begin
      buffer[bytesin] := #0;
      request := request + buffer;
      end
    else break; // read failed
  until SSL_pending(ssl) <= 0;
  // "request" is ready, though possibly empty
like image 536
Witness Protection ID 44583292 Avatar asked Jul 07 '11 20:07

Witness Protection ID 44583292


1 Answers

You are using SSL_pending() the completely wrong way. OpenSSL uses a state machine, where SSL_pending() indicates if the state machine has any pending bytes that have been buffered and are awaiting processing. Since you are never calling SSL_read(), you are never buffering any data or advancing the state machine.

like image 124
Remy Lebeau Avatar answered Sep 21 '22 20:09

Remy Lebeau