Skip to content

Commit 61fbca6

Browse files
committed
Remove ConnectionClosed/EmptyRead errors: these are not errors, they should be propagated as empty, successful reads
1 parent 109044b commit 61fbca6

File tree

5 files changed

+73
-27
lines changed

5 files changed

+73
-27
lines changed

src/integration/src/bin/pivot_remote_tls.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::panic;
22
use std::{
3-
io::{Read, Write},
3+
io::{ErrorKind, Read, Write},
44
sync::Arc,
55
};
66

@@ -63,18 +63,31 @@ impl RequestProcessor for Processor {
6363
);
6464

6565
tls.write_all(http_request.as_bytes()).unwrap();
66-
let _ciphersuite = tls.conn.negotiated_cipher_suite().unwrap();
6766

6867
let mut response_bytes = Vec::new();
69-
let read_to_end_result: usize =
70-
tls.read_to_end(&mut response_bytes).unwrap();
71-
72-
// Ignore eof errors: https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof
68+
let read_to_end_result = tls.read_to_end(&mut response_bytes);
69+
match read_to_end_result {
70+
Ok(read_size) => {
71+
assert!(read_size > 0);
72+
// Close the connection
73+
let closed = stream.close();
74+
closed.unwrap();
75+
}
76+
Err(e) => {
77+
// Only EOF errors are expected. This means the
78+
// connection was closed by the remote server https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof
79+
if e.kind() != ErrorKind::UnexpectedEof {
80+
panic!(
81+
"unexpected error trying to read_to_end: {e:?}"
82+
);
83+
}
84+
}
85+
}
7386

7487
let fetched_content =
7588
std::str::from_utf8(&response_bytes).unwrap();
7689
PivotRemoteTlsMsg::RemoteTlsResponse(format!(
77-
"Content fetched successfully ({read_to_end_result} bytes): {fetched_content}"
90+
"Content fetched successfully: {fetched_content}"
7891
))
7992
.try_to_vec()
8093
.expect("RemoteTlsResponse is valid borsh")

src/integration/tests/remote_tls.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,18 @@ fn fetch_remote_tls_content() {
4747
assert!(response_text.contains("Content fetched successfully"));
4848
assert!(response_text.contains("HTTP/1.1 200 OK"));
4949
assert!(response_text.contains("currentTime"));
50+
51+
let app_request = PivotRemoteTlsMsg::RemoteTlsRequest {
52+
host: "www.googleapis.com".to_string(),
53+
path: "/oauth2/v3/certs".to_string(),
54+
}
55+
.try_to_vec()
56+
.unwrap();
57+
58+
let response = enclave_client.send(&app_request).unwrap();
59+
let response_text = str::from_utf8(&response).unwrap();
60+
61+
assert!(response_text.contains("Content fetched successfully"));
62+
assert!(response_text.contains("HTTP/1.1 200 OK"));
63+
assert!(response_text.contains("keys"));
5064
}

src/qos_net/src/error.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ pub enum QosNetError {
2727
DuplicateConnectionId(u32),
2828
/// Attempt to send a message to a remote connection, but ID isn't found
2929
ConnectionIdNotFound(u32),
30-
/// Attempting to read on a closed remote connection (`.read` returned 0
31-
/// bytes)
32-
ConnectionClosed,
33-
/// Happens when a socket `read` results in no data
34-
EmptyRead,
3530
/// Happens when a socket `read` returns too much data for the provided
3631
/// buffer and the data doesn't fit. The first `usize` is the size of the
3732
/// received data, the second `usize` is the size of the buffer.

src/qos_net/src/proxy.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,12 @@ impl Proxy {
151151
// connection close. So we can safely remove it.
152152
match self.remove_connection(connection_id) {
153153
Ok(_) => {
154-
ProxyMsg::ProxyError(QosNetError::ConnectionClosed)
154+
// Connection was successfully removed / closed
155+
ProxyMsg::ReadResponse {
156+
connection_id,
157+
data: buf,
158+
size: 0,
159+
}
155160
}
156161
Err(e) => ProxyMsg::ProxyError(e),
157162
}

src/qos_net/src/proxy_stream.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ impl Read for ProxyStream {
184184
println!("READ {}: read {} bytes", buf.len(), size);
185185
Ok(size)
186186
}
187+
ProxyMsg::ProxyError(e) => Err(std::io::Error::new(
188+
ErrorKind::InvalidData,
189+
format!("Proxy error: {e:?}"),
190+
)),
187191
_ => Err(std::io::Error::new(
188192
ErrorKind::InvalidData,
189193
"unexpected response",
@@ -310,8 +314,8 @@ mod test {
310314

311315
#[test]
312316
fn can_fetch_tls_content_with_local_stream() {
313-
let host = "api.turnkey.com";
314-
let path = "/health";
317+
let host = "www.googleapis.com";
318+
let path = "/oauth2/v3/certs";
315319

316320
let mut stream = LocalStream::new_by_name(
317321
host.to_string(),
@@ -322,7 +326,10 @@ mod test {
322326
.unwrap();
323327
assert_eq!(stream.num_connections(), 1);
324328

325-
assert_eq!(stream.remote_hostname, Some("api.turnkey.com".to_string()));
329+
assert_eq!(
330+
stream.remote_hostname,
331+
Some("www.googleapis.com".to_string())
332+
);
326333

327334
let root_store =
328335
RootCertStore { roots: webpki_roots::TLS_SERVER_ROOTS.into() };
@@ -348,19 +355,27 @@ mod test {
348355
let mut response_bytes = Vec::new();
349356
let read_to_end_result = tls.read_to_end(&mut response_bytes);
350357

351-
// Ignore eof errors: https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof
352-
assert!(
353-
read_to_end_result.is_ok()
354-
|| (read_to_end_result
355-
.is_err_and(|e| e.kind() == ErrorKind::UnexpectedEof))
356-
);
357-
let response_text = std::str::from_utf8(&response_bytes).unwrap();
358-
assert!(response_text.contains("HTTP/1.1 200 OK"));
359-
assert!(response_text.contains("currentTime"));
358+
match read_to_end_result {
359+
Ok(read_size) => {
360+
assert!(read_size > 0);
361+
// Close the connection
362+
let closed = stream.close();
363+
assert!(closed.is_ok());
364+
}
365+
Err(e) => {
366+
// Only EOF errors are expected. This means the connection was
367+
// closed by the remote server https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof
368+
assert_eq!(e.kind(), ErrorKind::UnexpectedEof)
369+
}
370+
}
360371

361-
let closed = stream.close();
362-
assert!(closed.is_ok());
372+
// We should be at 0 connections in our proxy: either the remote
373+
// auto-closed (UnexpectedEof), or we did.
363374
assert_eq!(stream.num_connections(), 0);
375+
376+
let response_text = std::str::from_utf8(&response_bytes).unwrap();
377+
assert!(response_text.contains("HTTP/1.1 200 OK"));
378+
assert!(response_text.contains("keys"));
364379
}
365380

366381
/// Struct representing a stream, with direct access to the proxy.
@@ -447,6 +462,10 @@ mod test {
447462
println!("READ {}: read {} bytes", buf.len(), size);
448463
Ok(size)
449464
}
465+
ProxyMsg::ProxyError(e) => Err(std::io::Error::new(
466+
ErrorKind::InvalidData,
467+
format!("Proxy error: {e:?}"),
468+
)),
450469
_ => Err(std::io::Error::new(
451470
ErrorKind::InvalidData,
452471
"unexpected response",

0 commit comments

Comments
 (0)