cURL / Mailing Lists / curl-users / Single Mail

curl-users

[ curl-Bugs-653022 ] CPU consumed during ssl handshake

From: <noreply_at_sourceforge.net>
Date: Thu, 12 Dec 2002 15:58:31 -0800

Bugs item #653022, was opened at 2002-12-12 15:58
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=100976&aid=653022&group_id=976

Category: https
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Nobody/Anonymous (nobody)
Assigned to: Daniel Stenberg (bagder)
Summary: CPU consumed during ssl handshake

Initial Comment:
If the https server hangs during an ssl handshake, curl
gets stuck in a tight loop while attempting an
SSL_read. This could last an indefinite amount of time
and consumes the CPU. My suggested fix would be to
implement a similar select and timeout that curl uses for
SSL_connect, while also checking the SSL_pending
status of the ssl handle.

original code:

      nread = SSL_read(conn->ssl.handle, buf, buffersize);

      if(nread >= 0)
        /* successful read */
        break;

      err = SSL_get_error(conn->ssl.handle, nread);

      switch(err) {
      case SSL_ERROR_NONE: /* this is not an error */
      case SSL_ERROR_ZERO_RETURN: /* no more
data */
        loop=0; /* get out of loop */
        break;
      case SSL_ERROR_WANT_READ:
      case SSL_ERROR_WANT_WRITE:
        /* if there's data pending, then we re-invoke
SSL_read() */
        break;
      default:
        failf(conn->data, "SSL read error: %d", err);
        return CURLE_RECV_ERROR;
      }

Suggested fix:

      int what;
      fd_set writefd;
      fd_set readfd;
      struct timeval interval;
      long timeout_ms;

      nread = SSL_read(conn->ssl.handle, buf, buffersize);

      if(nread >= 0)
        /* successful read */
        break;

      err = SSL_get_error(conn->ssl.handle, nread);
    
      FD_ZERO(&writefd);
      FD_ZERO(&readfd);

      switch(err) {
      case SSL_ERROR_NONE: /* this is not an error */
      case SSL_ERROR_ZERO_RETURN: /* no more
data */
        loop=0; /* get out of loop */
        break;
      case SSL_ERROR_WANT_READ:
        /* check for pending ssl data that can be read */
        if(SSL_pending(conn->ssl.handle))
          continue;
        FD_SET(conn->firstsocket, &readfd);
        break;
      case SSL_ERROR_WANT_WRITE:
        FD_SET(conn->firstsocket, &writefd);
        break;
      default:
        failf(conn->data, "SSL read error: %d", err);
        return CURLE_RECV_ERROR;
      }

      /* Find out if any timeout is set. If not, use 300
seconds.
         Otherwise, figure out the most strict timeout of the
two possible one
         and then how much time that has elapsed to
know how much time we
         allow for the connect call */
      if(conn->data->set.timeout || conn->data-
>set.connecttimeout) {
        double has_passed;

        /* Evaluate in milliseconds how much time that
has passed */
        has_passed = Curl_tvdiff(Curl_tvnow(), conn->data-
>progress.start);

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

        /* get the most strict timeout of the ones converted
to milliseconds */
        if(conn->data->set.timeout &&
           (conn->data->set.timeout>conn->data-
>set.connecttimeout))
          timeout_ms = conn->data->set.timeout*1000;
        else
          timeout_ms = conn->data-
>set.connecttimeout*1000;
      
        /* subtract the passed time */
        timeout_ms -= (long)has_passed;
      
        if(timeout_ms < 0) {
          /* a precaution, no need to continue if time
already is up */
          failf(conn->data, "SSL connection timeout");
          return CURLE_OPERATION_TIMEOUTED;
        }
      }
      else
        /* no particular time-out has been set */
        timeout_ms=300000; /* milliseconds, default to five
minutes */

      interval.tv_sec = timeout_ms/1000;
      timeout_ms -= interval.tv_sec*1000;

      interval.tv_usec = timeout_ms*1000;

      what = select(conn->firstsocket+1, &readfd,
&writefd, NULL, &interval);
      if(what > 0)
        /* reabable or writable, go loop yourself */
        continue;
      else if(0 == what) {
        /* timeout */
        failf(conn->data, "SSL connection timeout");
        return CURLE_OPERATION_TIMEOUTED;
      }
      else
        break; /* get out of loop */

Submitter e-mail: evanjordan_at_hotmail.com

----------------------------------------------------------------------

You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=100976&aid=653022&group_id=976

-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
Received on 2002-12-13