pub extern crate rustls;
use std::borrow::Cow;
use std::io;
use std::io::BufWriter;
use std::net::TcpStream;
use std::net::ToSocketAddrs;
use std::sync::Arc;
use rustls::pki_types::ServerName;
use rustls::ClientConfig;
use rustls::ClientConnection;
use rustls::RootCertStore;
use rustls::StreamOwned;
use crate::format::SyslogContext;
use crate::sender::internal::impl_syslog_sender_common;
use crate::sender::internal::impl_syslog_stream_send_formatted;
pub fn rustls_well_known<S: Into<String>>(domain: S) -> io::Result<RustlsSender> {
let domain = domain.into();
rustls(format!("{domain}:6514"), domain)
}
pub fn rustls<A: ToSocketAddrs, S: Into<String>>(addr: A, domain: S) -> io::Result<RustlsSender> {
let mut roots = RootCertStore::empty();
for cert in rustls_native_certs::load_native_certs().certs {
roots.add(cert).unwrap();
}
let config = ClientConfig::builder()
.with_root_certificates(roots)
.with_no_client_auth();
rustls_with(addr, domain, Arc::new(config))
}
pub fn rustls_with<A: ToSocketAddrs, S: Into<String>>(
addr: A,
domain: S,
config: Arc<ClientConfig>,
) -> io::Result<RustlsSender> {
RustlsSender::connect(addr, domain, config)
}
#[derive(Debug)]
pub struct RustlsSender {
writer: BufWriter<StreamOwned<ClientConnection, TcpStream>>,
context: SyslogContext,
postfix: Cow<'static, str>,
}
impl RustlsSender {
pub fn connect<A: ToSocketAddrs, S: Into<String>>(
addr: A,
domain: S,
config: Arc<ClientConfig>,
) -> io::Result<Self> {
let domain = domain.into();
let domain = ServerName::try_from(domain).map_err(io::Error::other)?;
let stream = TcpStream::connect(addr)?;
let conn = ClientConnection::new(config, domain).map_err(io::Error::other)?;
let stream = StreamOwned::new(conn, stream);
Ok(Self {
writer: BufWriter::new(stream),
context: SyslogContext::default(),
postfix: Cow::Borrowed("\r\n"),
})
}
pub fn set_postfix(&mut self, postfix: impl Into<Cow<'static, str>>) {
self.postfix = postfix.into();
}
pub fn set_context(mut self, context: SyslogContext) {
self.context = context;
}
pub fn mut_context(&mut self) -> &mut SyslogContext {
&mut self.context
}
}
impl_syslog_sender_common!(RustlsSender);
impl_syslog_stream_send_formatted!(RustlsSender);