Skip to content

Commit 1c22384

Browse files
authored
Merge pull request #198 from cipherstash/terminate-on-close
fix: ensure terminate message is sent to server on connection close
2 parents 6e7f0b2 + 62d459d commit 1c22384

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

packages/cipherstash-proxy/src/postgresql/frontend.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::postgresql::context::column::Column;
1515
use crate::postgresql::context::Portal;
1616
use crate::postgresql::data::literal_from_sql;
1717
use crate::postgresql::messages::error_response::ErrorResponse;
18+
use crate::postgresql::messages::terminate::Terminate;
1819
use crate::postgresql::messages::Name;
1920
use crate::prometheus::{
2021
CLIENTS_BYTES_RECEIVED_TOTAL, ENCRYPTED_VALUES_TOTAL, ENCRYPTION_DURATION_SECONDS,
@@ -220,6 +221,13 @@ where
220221
Ok(())
221222
}
222223

224+
pub async fn terminate(&mut self) -> Result<(), Error> {
225+
debug!(target: PROTOCOL, msg = "Terminate server connection");
226+
let bytes = Terminate::message();
227+
self.write_to_server(bytes).await?;
228+
Ok(())
229+
}
230+
223231
async fn describe_handler(&mut self, bytes: &BytesMut) -> Result<(), Error> {
224232
let describe = Describe::try_from(bytes)?;
225233
debug!(target: PROTOCOL, client_id = self.context.client_id, ?describe);

packages/cipherstash-proxy/src/postgresql/handler.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,13 @@ pub async fn handler(
251251

252252
let client_to_server = async {
253253
loop {
254-
frontend.rewrite().await?;
254+
let result = frontend.rewrite().await;
255+
// Ensure the connection is terminated if the client closes the connection
256+
// The client ConnectionClosed error is triggered before the terminate message is passed through
257+
if matches!(result, Err(Error::ConnectionClosed)) {
258+
frontend.terminate().await?
259+
}
260+
result?;
255261
}
256262
// Unreachable, but helps the compiler understand the return type
257263
// TODO: extract into a function or something with type

packages/cipherstash-proxy/src/postgresql/messages/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod param_description;
1010
pub mod parse;
1111
pub mod query;
1212
pub mod row_description;
13+
pub mod terminate;
1314

1415
pub const NULL: i32 = -1;
1516

@@ -24,6 +25,7 @@ pub enum FrontendCode {
2425
SASLInitialResponse,
2526
SASLResponse,
2627
Sync,
28+
Terminate,
2729
Unknown(char),
2830
}
2931

@@ -72,6 +74,7 @@ impl From<char> for FrontendCode {
7274
#[allow(unreachable_patterns)]
7375
'p' => FrontendCode::SASLResponse, // Uses same char, here for completeness
7476
'S' => FrontendCode::Sync,
77+
'X' => FrontendCode::Terminate,
7578
_ => FrontendCode::Unknown(code),
7679
}
7780
}
@@ -89,6 +92,7 @@ impl From<FrontendCode> for u8 {
8992
FrontendCode::SASLInitialResponse => b'p',
9093
FrontendCode::SASLResponse => b'p',
9194
FrontendCode::Sync => b'S',
95+
FrontendCode::Terminate => b'X',
9296
FrontendCode::Unknown(c) => c as u8,
9397
}
9498
}
@@ -106,6 +110,7 @@ impl From<FrontendCode> for char {
106110
FrontendCode::SASLInitialResponse => 'p',
107111
FrontendCode::SASLResponse => 'p',
108112
FrontendCode::Sync => 'S',
113+
FrontendCode::Terminate => 'X',
109114
FrontendCode::Unknown(c) => c,
110115
}
111116
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use bytes::{BufMut, BytesMut};
2+
3+
use super::FrontendCode;
4+
5+
pub struct Terminate;
6+
7+
impl Terminate {
8+
pub fn message() -> BytesMut {
9+
let mut bytes = BytesMut::new();
10+
11+
bytes.put_u8(FrontendCode::Terminate.into());
12+
bytes.put_i32(4);
13+
14+
bytes
15+
}
16+
}

0 commit comments

Comments
 (0)