Fix nonblocking behavior

A new nonblocking socket may not have finished connecting yet, so reads
and writes can return ENOTCONNECTED which we should reinterpret into a
WantRead or WantWrite

Closes #323
This commit is contained in:
Steven Fackler 2015-12-17 16:54:11 -08:00
parent ccab187f5a
commit 053c924d5a
2 changed files with 17 additions and 22 deletions

View File

@ -95,7 +95,7 @@ unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_
match state.stream.write(buf) {
Ok(len) => len as c_int,
Err(err) => {
if err.kind() == io::ErrorKind::WouldBlock {
if retriable_error(&err) {
BIO_set_retry_write(bio);
}
state.error = Some(err);
@ -112,7 +112,7 @@ unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int)
match state.stream.read(buf) {
Ok(len) => len as c_int,
Err(err) => {
if err.kind() == io::ErrorKind::WouldBlock {
if retriable_error(&err) {
BIO_set_retry_read(bio);
}
state.error = Some(err);
@ -121,6 +121,13 @@ unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int)
}
}
fn retriable_error(err: &io::Error) -> bool {
match err.kind() {
io::ErrorKind::WouldBlock | io::ErrorKind::NotConnected => true,
_ => false
}
}
unsafe extern "C" fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
bwrite::<S>(bio, s, strlen(s) as c_int)
}

View File

@ -1070,16 +1070,10 @@ impl<S: Read + Write> SslStream<S> {
if ret > 0 {
Ok(stream)
} else {
match stream.make_old_error(ret) {
SslError::StreamError(e) => {
// This is fine - nonblocking sockets will finish the handshake in read/write
if e.kind() == io::ErrorKind::WouldBlock {
Ok(stream)
} else {
Err(SslError::StreamError(e))
}
}
e => Err(e),
match stream.make_error(ret) {
// This is fine - nonblocking sockets will finish the handshake in read/write
Error::WantRead(..) | Error::WantWrite(..) => Ok(stream),
_ => Err(stream.make_old_error(ret)),
}
}
}
@ -1092,16 +1086,10 @@ impl<S: Read + Write> SslStream<S> {
if ret > 0 {
Ok(stream)
} else {
match stream.make_old_error(ret) {
SslError::StreamError(e) => {
// This is fine - nonblocking sockets will finish the handshake in read/write
if e.kind() == io::ErrorKind::WouldBlock {
Ok(stream)
} else {
Err(SslError::StreamError(e))
}
}
e => Err(e),
match stream.make_error(ret) {
// This is fine - nonblocking sockets will finish the handshake in read/write
Error::WantRead(..) | Error::WantWrite(..) => Ok(stream),
_ => Err(stream.make_old_error(ret)),
}
}
}