I have a service written in Rust that receives an SSL acceptor and distributes SSL to some IPs collected from the database. The problem is that in some cases, this service hangs. Is there any way to stop the service and restart it from within the code that executes the connection if it encounters an error? Currently, we run it as a service in the task manager.
Func.rs:
use std::{
error::Error, io::{
ErrorKind, Read, Write
}, net::{
SocketAddrV4, TcpStream
}, sync::Arc, thread
};
use chrono::Local;
use gunion::ReadWrite;
use openssl::ssl::{
SslMethod,
// SslConnector,
SslAcceptor,
SslFiletype,
SslVerifyMode
};
type ReadToWrite = (Arc, Arc);
static mut ACCEPTOR: Option = None;
pub fn treat_con_default(listen: TcpStream, to: SocketAddrV4) -> Result<(), Box> {
let stream = TcpStream::connect(to)?;
let stream_c = stream.try_clone()?;
let listen_c = listen.try_clone()?;
for (mut s, mut l) in [(listen, stream), (stream_c, listen_c)] {
thread::spawn(move || {
let mut buf = [0u8; 2048];
while let Ok(size) = s.read(&mut buf) {
if let 0 = size {
break;
}
if let Err(err) = l.write(&buf[..size]) {
dbg!(err);
break;
}
}
ReadWrite::shutdown(&mut l);
});
}
Ok(())
}
pub fn treat_con_https(listen: TcpStream, to: SocketAddrV4) -> Result<(), Box> {
let listen = get_acceptor().accept(listen.try_clone()?)?;
let mut buf = [0u8; 2048];
let stream_t = Arc::new(TcpStream::connect(to)?);
let stream_c = Arc::clone(&stream_t);
let listen_t = Arc::new(listen);
let listen_c = Arc::clone(&listen_t);
let pairs: [ReadToWrite; 2] = [(listen_t, stream_t), (stream_c, listen_c)];
for (s, l) in pairs {
thread::spawn(move || {
Ok(unsafe {
let s: &mut dyn ReadWrite = &mut *(s.as_ref() as *const dyn ReadWrite as *mut _);
let l: &mut dyn ReadWrite = &mut *(l.as_ref() as *const dyn ReadWrite as *mut _);
loop {
match s.read(&mut buf) {
Ok(size) => {
if size == 0 {
break;
}
if let Err(err) = l.write(&buf[..size]) {
eprintln!("[{}][{}:{}] - Error writing to the stream: {:?}",
Local::now().format("%Y-%m-%d %H:%M:%S"),
file!(), line!(), err);
break;
}
},
Err(err) => {
if err.kind() != ErrorKind::ConnectionAborted {
eprintln!("[{}][{}:{}] - Error reading from stream: {:?}",
Local::now().format("%Y-%m-%d %H:%M:%S"), file!(), line!(), err);
break;
} else {
eprintln!("[{}][{}:{}] - Connection aborted while reading the stream. Trying to reconnect...",
Local::now().format("%Y-%m-%d %H:%M:%S"), file!(), line!());
}
return Err(Box::new(err));
}
}
}
l.shutdown();
})
});
}
Ok(())
}
pub fn get_acceptor() -> &'static mut SslAcceptor {
unsafe {
ACCEPTOR.get_or_insert_with(new_acceptor)
}
}
pub fn new_acceptor() -> SslAcceptor {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
acceptor.set_private_key_file(r"C:\conf\tracevia_key.pem", SslFiletype::PEM).unwrap();
acceptor.set_certificate_chain_file(r"C:\conf\tracevia_cert.pem").unwrap();
acceptor.set_verify_callback(SslVerifyMode::empty(), |_, _| true);
acceptor.check_private_key().unwrap();
acceptor.build()
}
main.rs:
\mod dao;
mod func;
use func::*;
use std::{mem, net::Ipv4Addr, thread, time::Duration};
use std::process;
use gunion::{Union, Direction, GetCallbackUnion, CallbackUnion};
use tracevia_tools::dao::{self as dao_tools, TraceviaDAO};
use log::{info, error};
use simplelog::{ColorChoice, CombinedLogger, Config, ConfigBuilder, LevelFilter, SharedLogger, SimpleLogger, TermLogger, TerminalMode, WriteLogger};
const MAX_ATTEMPTS: i32 = 5;
const MAX_RESTART_ATTEMPTS: i32 = 5;
const SERVICE_NAME: &str = " Union";
fn start_union(executable_path: String) {
if let Err(e) = start_some_service(executable_path) {
error!("Erro ao iniciar o serviço: {}", e);
}
}
fn start_some_service(executable_path: String) -> Result<(), Box> {
let executable_path_owned = executable_path.to_owned();
thread::spawn(move || {
let mut attempts = 0;
let mut attempts_restart = 0;
loop {
match some_function() {
Ok(_) => {
attempts = 0;
attempts_restart = 0;
thread::sleep(Duration::from_secs(1));
},
Err(e) => {
attempts += 1;
attempts_restart +=1;
error!("Erro na função some_function: {}. Tentativa {}/{} : {}/{}", e, attempts, MAX_ATTEMPTS, attempts_restart, MAX_RESTART_ATTEMPTS);
#[allow(unused_assignments)]
if attempts >= MAX_ATTEMPTS {
error!("Limite máximo de tentativas atingido. Reinciando...");
attempts = 0;
if attempts_restart == MAX_RESTART_ATTEMPTS {
attempts_restart = 0;
restart_application(executable_path_owned); // Reinicia a aplicação
break;
}
}
thread::sleep(Duration::from_secs(10));
}
}
}
});
Ok(())
I tried to create a function that would restart the initial SSL distribution function, but it didn’t work. Can you help me create one that can restart the service itself directly?
user25189610 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.