11use core:: net:: SocketAddr ;
22
3- use std:: io:: ErrorKind ;
4-
53use cryptoki:: object:: ObjectHandle ;
64use cryptoki:: types:: AuthPin ;
75use daemonbase:: error:: { ExitError , Failed } ;
6+ use kmip:: ttlv:: FastScanner ;
87use kmip:: types:: common:: Operation ;
98use kmip:: types:: request:: RequestMessage ;
109use kmip:: types:: response:: { BatchItem , ResultReason } ;
1110use kmip_ttlv:: PrettyPrinter ;
1211use kmip2pkcs11_cfg:: v1:: Config ;
1312use moka:: sync:: Cache ;
14- use tokio:: io:: AsyncWriteExt ;
13+ use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
1514use tokio:: net:: TcpStream ;
1615use tokio_rustls:: server:: TlsStream ;
1716use 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}\n Request 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 }.\n Request hex:\n {req_hex}\n Request dump:\n {req_human}\n " ,
129+ "Error while parsing KMIP request from client {peer_addr}: {error }.\n Request hex:\n {req_hex}\n Request 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,11 +140,12 @@ 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 } ;
119147
148+ buffer. drain ( ..request_bytes. len ( ) ) ;
120149 let res_bytes = mk_response ( res_batch_items) ;
121150
122151 if enabled ! ( Level :: DEBUG ) {
@@ -234,14 +263,3 @@ fn is_supported_protocol_version(req: &RequestMessage) -> bool {
234263 let minor_ver = ver. 1 . 0 ;
235264 major_ver == 1 && minor_ver <= 2
236265}
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