From 887d13cd113bf1a43e2ecc61910c0603c1b98cde Mon Sep 17 00:00:00 2001 From: HMasataka <76937492+HMasataka@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:04:22 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20thiserror,=20tracing=E3=82=AF=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=81=AE=E5=B0=8E=E5=85=A5=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 164 ++++++++++++++++++++++++++++++++++++ clocking-server/Cargo.toml | 5 ++ clocking-server/src/cert.rs | 34 ++++++++ clocking-server/src/err.rs | 29 +++++++ clocking-server/src/main.rs | 73 +++++++++++----- 5 files changed, 286 insertions(+), 19 deletions(-) create mode 100644 clocking-server/src/cert.rs create mode 100644 clocking-server/src/err.rs diff --git a/Cargo.lock b/Cargo.lock index ec1adcb..ee1f15c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,8 +248,13 @@ dependencies = [ "clap", "dotenvy", "rustls-pemfile", + "thiserror", "tokio", "tokio-rustls", + "tracing", + "tracing-error", + "tracing-subscriber", + "tracing_spanned", ] [[package]] @@ -468,6 +473,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "object" version = "0.36.3" @@ -483,6 +498,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -673,6 +694,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -733,6 +763,36 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tokio" version = "1.39.2" @@ -773,6 +833,82 @@ dependencies = [ "tokio", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing_spanned" +version = "0.1.0" +source = "git+https://github.com/comnipl/tracing_spanned?rev=6fed6097d13d117e4d35120f56450b156c33b77e#6fed6097d13d117e4d35120f56450b156c33b77e" +dependencies = [ + "tracing", + "tracing-error", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -791,6 +927,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -809,6 +951,28 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/clocking-server/Cargo.toml b/clocking-server/Cargo.toml index c2d6336..75d863d 100644 --- a/clocking-server/Cargo.toml +++ b/clocking-server/Cargo.toml @@ -7,5 +7,10 @@ edition = "2021" clap = { version = "4.5.15", features = ["derive", "env"] } dotenvy = "0.15.7" rustls-pemfile = "2.1.3" +thiserror = "1.0.64" tokio = { version = "1", features = ["full"] } tokio-rustls = "0.26.0" +tracing = "0.1.40" +tracing-error = "0.2.0" +tracing-subscriber = "0.3.18" +tracing_spanned = { git = "https://github.com/comnipl/tracing_spanned", rev = "6fed6097d13d117e4d35120f56450b156c33b77e" } diff --git a/clocking-server/src/cert.rs b/clocking-server/src/cert.rs new file mode 100644 index 0000000..ac0f722 --- /dev/null +++ b/clocking-server/src/cert.rs @@ -0,0 +1,34 @@ +use crate::err::ClockerError; + +use std::fs::File; +use std::io::BufReader; +use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer}; +use tracing::instrument; +use tracing_spanned::SpanErr; + +#[instrument(skip_all, name = "read_cert_file", level = "trace")] +pub fn read_cert_file( + cert_path: String, +) -> Result>, SpanErr> { + let mut cert_file = File::open(cert_path).map_err(ClockerError::LoadCertFile)?; + + let cert = rustls_pemfile::certs(&mut BufReader::new(&mut cert_file)) + .collect::, _>>() + .map_err(ClockerError::LoadCertFile)?; + + Ok(cert) +} + +#[instrument(skip_all, name = "read_private_key_file", level = "trace")] +pub fn read_private_key_file( + private_key_path: String, +) -> Result, SpanErr> { + let mut private_key_file = + File::open(private_key_path).map_err(ClockerError::LoadPrivateKeyFile)?; + + let private_key = rustls_pemfile::private_key(&mut BufReader::new(&mut private_key_file)) + .map_err(ClockerError::LoadPrivateKeyFile)? + .ok_or(ClockerError::ReadPrivateKeyPEMSection)?; + + Ok(private_key) +} diff --git a/clocking-server/src/err.rs b/clocking-server/src/err.rs new file mode 100644 index 0000000..b69e238 --- /dev/null +++ b/clocking-server/src/err.rs @@ -0,0 +1,29 @@ +use std::{io, string::FromUtf8Error}; + +use thiserror::Error; +use tokio_rustls::rustls; +use tracing_subscriber::util::TryInitError; + +#[derive(Error, Debug)] +pub enum ClockerError { + #[error("initialize tracing subscriber error: {0}")] + InitializeTracingSubscriber(TryInitError), + #[error("create tcp listener error: {0}, port: {1}")] + CreateTCPListener(io::Error, u16), + #[error("failed to accept new connection")] + AcceptNewConnection(io::Error), + #[error("failed to accept new stream")] + AcceptNewStream(io::Error), + #[error("private key pem section not found")] + ReadPrivateKeyPEMSection, + #[error("build tls server error: {0}")] + BuildServer(rustls::Error), + #[error("failed to load cert file: {0}")] + LoadCertFile(io::Error), + #[error("failed to load private key file: {0}")] + LoadPrivateKeyFile(io::Error), + #[error("failed to read buffer: {0}")] + ReadBuffer(io::Error), + #[error("failed to convert buffer to string: {0}")] + ConvertBufferToString(FromUtf8Error), +} diff --git a/clocking-server/src/main.rs b/clocking-server/src/main.rs index 9df6ec2..81969d3 100644 --- a/clocking-server/src/main.rs +++ b/clocking-server/src/main.rs @@ -1,13 +1,19 @@ +mod cert; +mod err; + +use cert::{read_cert_file, read_private_key_file}; use clap::Parser; use dotenvy::dotenv; -use std::error::Error; -use std::fs::File; -use std::io::BufReader; +use err::ClockerError; use std::net::Ipv4Addr; use std::sync::Arc; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpListener, TcpStream}; use tokio_rustls::{rustls, TlsAcceptor}; +use tracing::instrument; +use tracing_error::ErrorLayer; +use tracing_spanned::SpanErr; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -20,19 +26,42 @@ struct Args { private_key_path: String, } +#[instrument(skip_all, name = "initialize_tracing_subscriber", level = "trace")] +fn initialize_tracing_subscriber() -> Result<(), SpanErr> { + tracing_subscriber::Registry::default() + .with( + tracing_subscriber::fmt::layer() + .with_target(false) + .with_filter(tracing_subscriber::filter::LevelFilter::INFO), + ) + .with(ErrorLayer::default()) + .try_init() + .map_err(ClockerError::InitializeTracingSubscriber)?; + + Ok(()) +} + #[tokio::main] -async fn main() -> Result<(), Box> { +#[instrument(skip_all, name = "main", level = "trace")] +async fn main() -> Result<(), SpanErr> { + initialize_tracing_subscriber()?; + let _ = dotenv(); let args = Args::parse(); - let listener = TcpListener::bind((Ipv4Addr::UNSPECIFIED, args.port)).await?; + let listener = TcpListener::bind((Ipv4Addr::UNSPECIFIED, args.port)) + .await + .map_err(|e| ClockerError::CreateTCPListener(e, args.port))?; - let acceptor = - get_tls_acceptor(args.cert_path, args.private_key_path).expect("get tls acceptor error"); + let acceptor = get_tls_acceptor(args.cert_path, args.private_key_path)?; loop { - let (stream, _) = listener.accept().await?; + let (stream, _) = listener + .accept() + .await + .map_err(ClockerError::AcceptNewConnection)?; + let acceptor = acceptor.clone(); tokio::spawn(async move { @@ -41,31 +70,37 @@ async fn main() -> Result<(), Box> { } } +#[instrument(skip_all, name = "get_tls_acceptor", level = "trace")] fn get_tls_acceptor( cert_path: String, private_key_path: String, -) -> Result> { - let cert_file = rustls_pemfile::certs(&mut BufReader::new(&mut File::open(cert_path)?)) - .collect::, _>>()?; +) -> Result> { + let cert = read_cert_file(cert_path)?; - let private_key_file = - rustls_pemfile::private_key(&mut BufReader::new(&mut File::open(private_key_path)?))? - .unwrap(); + let private_key = read_private_key_file(private_key_path)?; let config = rustls::ServerConfig::builder() .with_no_client_auth() - .with_single_cert(cert_file, private_key_file)?; + .with_single_cert(cert, private_key) + .map_err(ClockerError::BuildServer)?; Ok(TlsAcceptor::from(Arc::new(config))) } -async fn process(acceptor: TlsAcceptor, stream: TcpStream) -> Result<(), Box> { - let mut tls_stream = acceptor.accept(stream).await?; +#[instrument(skip_all, name = "process", level = "trace")] +async fn process(acceptor: TlsAcceptor, stream: TcpStream) -> Result<(), SpanErr> { + let mut tls_stream = acceptor + .accept(stream) + .await + .map_err(ClockerError::AcceptNewStream)?; let mut buf = Vec::with_capacity(4096); - tls_stream.read_buf(&mut buf).await?; + let _ = tls_stream + .read_buf(&mut buf) + .await + .map_err(ClockerError::ReadBuffer)?; - let msg = String::from_utf8(buf)?; + let msg = String::from_utf8(buf).map_err(ClockerError::ConvertBufferToString)?; let result = tls_stream.write(msg.as_bytes()).await; println!(