mod client; mod pseudo_tcp_message; mod server; mod socket; mod state; pub mod prelude; #[cfg(feature = "hostname")] mod hostname; #[cfg(feature = "local_ip")] mod local_address; #[cfg(feature = "public_ip")] mod public_address; #[cfg(feature = "resolve_dns")] mod resolve; use crate::prelude::*; use std::{ fs::File, io::{Error, Write}, mem::swap, net::SocketAddr, sync::Mutex, }; use chrono::Local; static LOG_FILE: Mutex> = Mutex::new(None); pub struct NetworkLogFile { file: File, } impl NetworkLogFile { pub fn create(path: &str) -> std::result::Result<(), Error> { let mut file = File::create(path)?; file.write_all("================================================\n".as_bytes())?; file.write_all(format!("{:?}\n", Local::now()).as_bytes())?; file.write_all("================================================\n\n\n".as_bytes())?; *LOG_FILE.lock().unwrap() = Some(NetworkLogFile { file }); Ok(()) } pub(crate) fn log(mut message: String) -> std::result::Result<(), Error> { message += "\n"; LOG_FILE .lock() .unwrap() .as_mut() .expect("log file not set!") .file .write_all(message.as_bytes()) } } pub fn split_matches(s: &str, c: char) -> (&str, &str) { match s.find(c) { Some(pos) => { let (f, l) = s.split_at(pos); let l = l.trim_start_matches(c); (f, l) } None => (s, ""), } } pub fn filter_by_content(content: &mut Vec, mut filter: F) -> Vec where F: FnMut(SocketAddr, &str) -> bool, { let mut v = Vec::new(); swap(content, &mut v); let (filtered, others): (Vec, Vec) = v.into_iter().partition(|content| match content { SocketContent::Message(addr, msg) => filter(*addr, msg), SocketContent::NewConnection(_) => false, SocketContent::TimeOut(_) => false, }); *content = others; filtered } pub trait Sender { fn send(&mut self, addr: SocketAddr, msg: &str) -> anyhow::Result<()>; fn is_server(&self) -> bool; }