Skip to content

Commit e92bcdb

Browse files
committed
Use 'kmip::ttlv::FastScanner' for scanning
1 parent 5a274c0 commit e92bcdb

File tree

1 file changed

+56
-39
lines changed

1 file changed

+56
-39
lines changed

src/client_request_handler.rs

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
use core::net::SocketAddr;
22

3-
use std::io::ErrorKind;
4-
53
use cryptoki::object::ObjectHandle;
64
use cryptoki::types::AuthPin;
75
use daemonbase::error::{ExitError, Failed};
6+
use kmip::ttlv::FastScanner;
87
use kmip::types::common::Operation;
98
use kmip::types::request::RequestMessage;
109
use kmip::types::response::{BatchItem, ResultReason};
1110
use kmip_ttlv::PrettyPrinter;
1211
use kmip2pkcs11_cfg::v1::Config;
1312
use moka::sync::Cache;
14-
use tokio::io::AsyncWriteExt;
13+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
1514
use tokio::net::TcpStream;
1615
use tokio_rustls::server::TlsStream;
1716
use tracing::{Level, debug, enabled, error, info, warn};
@@ -30,29 +29,63 @@ pub async fn handle_client_requests(
3029
mut config: Config,
3130
mut pkcs11_pools: Pkcs11Pools,
3231
) -> Result<(), ExitError> {
33-
let reader_config = kmip::Config::new();
3432
let tag_map = kmip::tag_map::make_kmip_tag_map();
3533
let enum_map = kmip::tag_map::make_kmip_enum_map();
3634
let pp = PrettyPrinter::new()
3735
.with_tag_prefix("4200".into())
3836
.with_tag_map(tag_map)
3937
.with_enum_map(enum_map);
4038

39+
// A buffer accumulating data read thus far.
40+
//
41+
// TODO: Use a more efficient buffer type, that can avoid shifting the data
42+
// every time a request message is consumed.
43+
let mut buffer = Vec::with_capacity(8192);
44+
4145
loop {
42-
if let Err(err) = stream.get_ref().0.readable().await {
43-
// Don't warn about client disconnection.
44-
// TODO: Categorize the various std::io::ErrorKinds into fatal and
45-
// non-fatal variants and only abort on fatal errors.
46-
if err.kind() != ErrorKind::UnexpectedEof {
47-
warn!("Closing connection with client {peer_addr} due to error: {err}");
46+
// Try parsing a request message from buffered data.
47+
let (request, request_bytes) = loop {
48+
// Try reading from the buffer.
49+
let available = buffer.len() - buffer.len() % 8;
50+
let mut scanner = FastScanner::new(&buffer[..available])
51+
.expect("the provided buffer has a multiple of 8 bytes");
52+
if scanner.have_next() {
53+
// A complete TTLV element is available. Try to parse it.
54+
let request = RequestMessage::fast_scan(&mut scanner);
55+
let consumed = available - scanner.remaining().as_flattened().len();
56+
break (request, &buffer[..consumed]);
4857
}
49-
return Ok(());
50-
}
58+
59+
// 'buffer' did not contain enough data. Try to add to it.
60+
match stream.read_buf(&mut buffer).await {
61+
// The client has closed the connection.
62+
Ok(0) => {
63+
if !buffer.is_empty() {
64+
warn!(
65+
"Client {peer_addr} closed connection with a partial request received"
66+
);
67+
}
68+
return Ok(());
69+
}
70+
71+
// Some data was received successfully.
72+
Ok(_) => {}
73+
74+
// An unexpected error has occurred.
75+
Err(err) => {
76+
// TODO: Categorize the various std::io::ErrorKinds into
77+
// fatal and non-fatal variants and only abort on fatal
78+
// errors.
79+
warn!("Closing connection with client {peer_addr} due to error: {err}");
80+
return Ok(());
81+
}
82+
};
83+
};
5184

5285
let mut res_batch_items = vec![];
5386

54-
match kmip_ttlv::from_reader::<RequestMessage, _>(&mut stream, &reader_config).await {
55-
Ok((req, _cap)) if !is_supported_protocol_version(&req) => {
87+
match request {
88+
Ok(request) if !is_supported_protocol_version(&request) => {
5689
// https://docs.oasis-open.org/kmip/spec/v1.2/os/kmip-spec-v1.2-os.html#_Toc409613599
5790
// 11 Error Handling
5891
// 11.1 General
@@ -68,15 +101,15 @@ pub async fn handle_client_requests(
68101
));
69102
}
70103

71-
Ok((req, req_bytes)) => {
104+
Ok(request) => {
72105
if enabled!(Level::DEBUG) {
73-
let req_hex = mk_kmip_hex_dump(&req_bytes);
74-
let req_human = pp.to_string(&req_bytes);
106+
let req_hex = mk_kmip_hex_dump(&request_bytes);
107+
let req_human = pp.to_string(&request_bytes);
75108
debug!("Request hex:\n{req_hex}\nRequest dump:\n{req_human}\n");
76109
}
77110

78111
let (res, c, p) = tokio::task::spawn_blocking(move || {
79-
let r = process_request(&config, &pkcs11_pools, peer_addr, req);
112+
let r = process_request(&config, &pkcs11_pools, peer_addr, request);
80113
(r, config, pkcs11_pools)
81114
})
82115
.await
@@ -88,17 +121,12 @@ pub async fn handle_client_requests(
88121
res_batch_items.append(&mut res?);
89122
}
90123

91-
Err((err, _cap)) if is_disconnection_err(&err) => {
92-
// The client has gone, terminate this response stream processor.
93-
break Ok(());
94-
}
95-
96-
Err((err, res_bytes)) => {
97-
let req_hex = mk_kmip_hex_dump(&res_bytes);
98-
let req_human = pp.to_string(&res_bytes);
124+
Err(error) => {
125+
let req_hex = mk_kmip_hex_dump(&request_bytes);
126+
let req_human = pp.to_string(&request_bytes);
99127

100128
error!(
101-
"Error while parsing KMIP request from client {peer_addr}: {err}.\nRequest hex:\n{req_hex}\nRequest dump:\n{req_human}\n",
129+
"Error while parsing KMIP request from client {peer_addr}: {error}.\nRequest hex:\n{req_hex}\nRequest dump:\n{req_human}\n",
102130
);
103131

104132
// https://docs.oasis-open.org/kmip/spec/v1.2/os/kmip-spec-v1.2-os.html#_Toc409613599
@@ -112,7 +140,7 @@ pub async fn handle_client_requests(
112140
// Operation Failed"
113141
res_batch_items.push(mk_err_batch_item(
114142
ResultReason::GeneralFailure,
115-
format!("Unable to parse KMIP TTLV request: {err}"),
143+
format!("Unable to parse KMIP TTLV request: {error}"),
116144
));
117145
}
118146
};
@@ -234,14 +262,3 @@ fn is_supported_protocol_version(req: &RequestMessage) -> bool {
234262
let minor_ver = ver.1.0;
235263
major_ver == 1 && minor_ver <= 2
236264
}
237-
238-
pub fn is_disconnection_err(err: &kmip_ttlv::error::Error) -> bool {
239-
if let kmip_ttlv::error::ErrorKind::IoError(err) = err.kind() {
240-
matches!(
241-
err.kind(),
242-
std::io::ErrorKind::UnexpectedEof | std::io::ErrorKind::ConnectionReset
243-
)
244-
} else {
245-
false
246-
}
247-
}

0 commit comments

Comments
 (0)