From: Jason Ish Date: Mon, 9 Jun 2025 01:43:24 +0000 (-0600) Subject: suricatasc: reconnect on loss of connection X-Git-Tag: suricata-8.0.0-rc1~121 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=89ba53272c91f16b2f612ea6812541cb24d7b285;p=thirdparty%2Fsuricata.git suricatasc: reconnect on loss of connection If the connection is lost (for example, Suricata is restarted), try to re-open the connect and re-execute the command. This was the behavior of the Python implementation. Ticket: #7746 --- diff --git a/rust/suricatasc/src/unix/client.rs b/rust/suricatasc/src/unix/client.rs index 0c2d381d2f..9ba55e3096 100644 --- a/rust/suricatasc/src/unix/client.rs +++ b/rust/suricatasc/src/unix/client.rs @@ -19,6 +19,7 @@ pub enum ClientError { } pub struct Client { + filename: String, socket: UnixStream, // If set, the client will print to stdout the messages sent and @@ -30,12 +31,25 @@ pub struct Client { impl Client { pub fn connect>(filename: T, verbose: bool) -> Result { let filename = filename.as_ref().to_string(); - let socket = UnixStream::connect(filename)?; - let mut client = Self { socket, verbose }; + let socket = UnixStream::connect(&filename)?; + let mut client = Self { + filename, + socket, + verbose, + }; client.handshake()?; Ok(client) } + pub fn reconnect(&mut self) -> Result<(), ClientError> { + if self.verbose { + println!("Reconnecting to socket: {}", self.filename); + } + self.socket = UnixStream::connect(&self.filename)?; + self.handshake()?; + Ok(()) + } + fn handshake(&mut self) -> Result<(), ClientError> { self.send(&json!({"version": "0.2"}))?; self.read().map(serde_json::from_value::)??; diff --git a/rust/suricatasc/src/unix/main.rs b/rust/suricatasc/src/unix/main.rs index e1b7aa45aa..535ae8d116 100644 --- a/rust/suricatasc/src/unix/main.rs +++ b/rust/suricatasc/src/unix/main.rs @@ -71,27 +71,42 @@ fn run_interactive(mut client: Client) -> Result<(), Box> if line.starts_with("quit") { break; } - match command_parser.parse(&line) { - Ok(command) => match interactive_request_response(&mut client, &command) { - Ok(response) => { - let response: Response = serde_json::from_value(response).unwrap(); - if response.status == "OK" { - println!("Success:"); - println!( - "{}", - serde_json::to_string_pretty(&response.message).unwrap() - ); - } else { - println!("Error:"); - println!("{}", serde_json::to_string(&response.message).unwrap()); + let mut retry = false; + loop { + match command_parser.parse(&line) { + Ok(command) => match interactive_request_response(&mut client, &command) { + Ok(response) => { + let response: Response = serde_json::from_value(response).unwrap(); + if response.status == "OK" { + println!("Success:"); + println!( + "{}", + serde_json::to_string_pretty(&response.message).unwrap() + ); + } else { + println!("Error:"); + println!("{}", serde_json::to_string(&response.message).unwrap()); + } + break; } - } + Err(err) => { + println!("Error: {}", err); + if retry { + break; + } + if let Err(err) = client.reconnect() { + println!("Error: {}", &err); + break; + } else { + retry = true; + continue; + } + } + }, Err(err) => { println!("{}", err); + break; } - }, - Err(err) => { - println!("{}", err); } } }