GNUTLS: Improve rb_ssl_read_or_write()
* Set errno to 0 before attempting any read/write operations as it may affect our tests otherwise. * Properly check whether the gnutls_record_recv()/gnutls_record_send() call failed and distinguish between kernel and library errors.
This commit is contained in:
parent
d4e71871c0
commit
0071c423d5
1 changed files with 17 additions and 19 deletions
|
@ -304,32 +304,30 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
if(r_or_w == 0)
|
if(r_or_w == 0)
|
||||||
ret = gnutls_record_recv(SSL_P(F), rbuf, count);
|
ret = gnutls_record_recv(SSL_P(F), rbuf, count);
|
||||||
else
|
else
|
||||||
ret = gnutls_record_send(SSL_P(F), wbuf, count);
|
ret = gnutls_record_send(SSL_P(F), wbuf, count);
|
||||||
|
|
||||||
if(ret < 0)
|
if(ret >= 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if(ret == GNUTLS_E_AGAIN || (ret == GNUTLS_E_INTERRUPTED && (errno == 0 || rb_ignore_errno(errno))))
|
||||||
{
|
{
|
||||||
switch (ret)
|
if(gnutls_record_get_direction(SSL_P(F)) == 0)
|
||||||
{
|
return RB_RW_SSL_NEED_READ;
|
||||||
case GNUTLS_E_AGAIN:
|
else
|
||||||
case GNUTLS_E_INTERRUPTED:
|
return RB_RW_SSL_NEED_WRITE;
|
||||||
if(rb_ignore_errno(errno))
|
|
||||||
{
|
|
||||||
if(gnutls_record_get_direction(*ssl) == 0)
|
|
||||||
return RB_RW_SSL_NEED_READ;
|
|
||||||
else
|
|
||||||
return RB_RW_SSL_NEED_WRITE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
F->ssl_errno = (unsigned long) -ret;
|
|
||||||
errno = EIO;
|
|
||||||
return RB_RW_IO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
if(ret == GNUTLS_E_INTERRUPTED && errno != 0)
|
||||||
|
return RB_RW_IO_ERROR;
|
||||||
|
|
||||||
|
errno = EIO;
|
||||||
|
F->ssl_errno = (unsigned long) -ret;
|
||||||
|
return RB_RW_SSL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
|
|
Loading…
Reference in a new issue