[Spice-devel] [PATCH 05/13] server/reds: RFC: improve ssl_{read, write} return values

Alon Levy alevy at redhat.com
Thu Feb 24 10:14:52 PST 2011


On Tue, Feb 22, 2011 at 05:08:59PM +0100, Marc-André Lureau wrote:
> There is no known bug related to this patch, it might cause more harm
> than good.
> 
> The implementation of ssl_writev() looks incorrect: it never returned
> an error (return_code is always >= 0).

Actually it does - if the first call to write fails, then return_code==0,
so return_code<=0, and so it returns n.

> But, it should return the
> number of bytes written before it reached EAGAIN, otherwise, we risk
> of sending corrupted data.

It did that already.

If the first (or more then first) calls succeed, return_code would
accumulate the non zero n, so it will be positive, so return_code >0,
so ! return_code <= 0, and so when n <= 0 (the last failed call) it
will break, and then return return_code, the accumulated number of sent
bytes.

> 
> Finally, since the SSL usage is hidden from the reader/writter, and it
> assumes it is a fd-kind/libc of API (checking ERRNO), we should make
> sure errno is set to a correct value in that case (EAGAIN for instance).
> 
That (plus style changes) is what this patch adds. I have no idea if we
use errno somewhere, no idea if this change is good or bad. It looks good
looking at the callers (in red_channel.c red_peer_handle_outgoing for instance).

> Note: we should be careful with the polling of SSL fd, since
> SSL_read() or SSL_write() both can return WANT_READ or WANT_WRITE.  We
> should poll both IN and OUT, not sure how it's handled now.
me neither. Do you mean that after a WANT_READ we should only do a SSL_read and
not do a SSL_write?

> ---
>  server/reds.c |   31 +++++++++++++++++++------------
>  1 files changed, 19 insertions(+), 12 deletions(-)
> 
> diff --git a/server/reds.c b/server/reds.c
> index 45e4964..2aefe31 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -319,6 +319,13 @@ static ssize_t stream_read_cb(RedsStream *s, void *buf, size_t size)
>      return read(s->socket, buf, size);
>  }
>  
> +static void ssl_error_eagain(int error)
> +{
> +    /* can this help? */
> +    if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
> +        errno = EAGAIN;
> +}
> +
>  static ssize_t stream_ssl_write_cb(RedsStream *s, const void *buf, size_t size)
>  {
>      int return_code;
> @@ -326,8 +333,10 @@ static ssize_t stream_ssl_write_cb(RedsStream *s, const void *buf, size_t size)
>  
>      return_code = SSL_write(s->ssl, buf, size);
>  
> -    if (return_code < 0)
> +    if (return_code < 0) {
>          ssl_error = SSL_get_error(s->ssl, return_code);
> +        ssl_error_eagain(ssl_error); /* just to be sure */
> +    }
>  
>      return return_code;
>  }
> @@ -339,8 +348,10 @@ static ssize_t stream_ssl_read_cb(RedsStream *s, void *buf, size_t size)
>  
>      return_code = SSL_read(s->ssl, buf, size);
>  
> -    if (return_code < 0)
> +    if (return_code < 0) {
>          ssl_error = SSL_get_error(s->ssl, return_code);
> +        ssl_error_eagain(ssl_error); /* just to be sure */
> +    }
>  
>      return return_code;
>  }
> @@ -349,24 +360,20 @@ static ssize_t stream_ssl_writev_cb(RedsStream *s, const struct iovec *vector, i
>  {
>      int i;
>      int n;
> -    ssize_t return_code = 0;
> +    ssize_t ret = 0;
>      int ssl_error;
>  
>      for (i = 0; i < count; ++i) {
>          n = SSL_write(s->ssl, vector[i].iov_base, vector[i].iov_len);
>          if (n <= 0) {
>              ssl_error = SSL_get_error(s->ssl, n);
> -            if (return_code <= 0) {
> -                return n;
> -            } else {
> -                break;
> -            }
> -        } else {
> -            return_code += n;
> -        }
> +            ssl_error_eagain(ssl_error); /* just to be sure we have EAGAIN */
> +            return ret == 0 ? n : ret;
> +        } else
> +            ret += n;
>      }
>  
> -    return return_code;
> +    return ret;
>  }
>  
>  static void reds_stream_remove_watch(RedsStream* s)
> -- 
> 1.7.4
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list