From 790ed2a0bb81f8260736498ee5cf0218c3055de0 Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 17:59:13 -0800 Subject: [PATCH 1/9] dependency updates, error handling, modernize rust --- Cargo.toml | 34 ++++-- Makefile | 6 +- examples/session_watcher/src/main.rs | 5 +- src/error.rs | 114 ++++-------------- src/lib.rs | 2 +- src/net/addr.rs | 2 +- src/net/datagram.rs | 39 +++--- src/net/i2p.rs | 14 +-- src/net/mod.rs | 22 ++-- src/net/streaming.rs | 53 ++++----- src/sam.rs | 98 ++++++++------- src/sam_options.rs | 31 ++--- src/session_watcher.rs | 170 ++++++++++++++------------- 13 files changed, 277 insertions(+), 313 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8b88a77..2fc89b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" categories = ["network-programming"] keywords = ["i2p", "net", "network", "sam"] license = "MIT" -edition = "2018" +edition = "2021" [features] default = ["public-conn"] @@ -17,17 +17,27 @@ public-conn = [] [badges] travis-ci = { repository = "i2p/i2p-rs" } -[dependencies] -data-encoding = "2.1.2" -failure = "0.1" -failure_derive = "0.1" -lazy_static = "1.3.0" -log = "0.4.6" -nom = "^4.2" -rand = "0.5" -serde = "1" -serde_derive = "1" -sha2 = "0.8.0" +[dependencies.data-encoding] +version = "2" +[dependencies.serde] +version = "1" +features = ["derive"] +[dependencies.anyhow] +version = "1" +[dependencies.thiserror] +version = "1" +[dependencies.lazy_static] +version = "1" +[dependencies.log] +version = "0.4" +[dependencies.nom] +version = "^4.2" +[dependencies.rand] +version = "0.5" +[dependencies.sha2] +version = "0.8" +[dependencies.dashmap] +dashmap = "5" [dev-dependencies] env_logger = "0.5" diff --git a/Makefile b/Makefile index 569517f..846b308 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ .PHONY: fmt fmt: - find -type f -name "*.rs" -not -path "*target*" -exec rustfmt --edition 2018 {} \; \ No newline at end of file + find -type f -name "*.rs" -not -path "*target*" -exec rustfmt --edition 2021 {} \; + +.PHONY: lint +lint: + cargo +nightly clippy --fix -Z unstable-options --release --all \ No newline at end of file diff --git a/examples/session_watcher/src/main.rs b/examples/session_watcher/src/main.rs index fb6da1b..a885c4e 100644 --- a/examples/session_watcher/src/main.rs +++ b/examples/session_watcher/src/main.rs @@ -32,8 +32,9 @@ async fn main() { DEFAULT_API, &seckey, SessionStyle::Stream, - Default::default() - ).unwrap(); + Default::default(), + ) + .unwrap(); loop { match watcher.accept() { diff --git a/src/error.rs b/src/error.rs index a20c51c..96806b3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,117 +1,51 @@ +use nom; use std::fmt::{self, Display}; use std::io; - -use failure::{Backtrace, Context, Fail}; -use nom; - -/// I2P/SAM error definition -#[derive(Debug, Fail)] -pub struct Error { - inner: Context, -} +use thiserror::Error as ThisError; /// Kinds of I2P/SAM errors -#[derive(Clone, Eq, PartialEq, Debug, Fail)] -pub enum ErrorKind { +#[derive(Clone, Eq, PartialEq, Debug, ThisError)] +pub enum I2PError { /// Wraps io errors - #[fail(display = "IO error occurred (is i2p running?): {}", _0)] + #[error("IO error occurred (is i2p running?): {0}")] Io(String), /// Wraps nom parser errors - #[fail(display = "Failed to parse an I2P/SAM message")] + #[error("Failed to parse an I2P/SAM message")] MessageParsing, - #[fail(display = "Failed to parse an I2P/SAM message")] + #[error("Failed to parse an I2P/SAM message")] UnresolvableAddress, - #[fail(display = "Invalid or unrecognized I2P/SAM message: {}", _0)] + #[error("Invalid or unrecognized I2P/SAM message: {0}")] SAMInvalidMessage(String), - #[fail(display = "Can't reach peer: {}", _0)] + #[error("Can't reach peer: {0}")] SAMCantReachPeer(String), - #[fail(display = "Destination key not found: {}", _0)] + #[error("Destination key not found: {0}")] SAMKeyNotFound(String), - #[fail(display = "Peer not found: {}", _0)] + #[error("Peer not found: {0}")] SAMPeerNotFound(String), - #[fail(display = "Duplicate peer destination: {}", _0)] + #[error("Duplicate peer destination: {0}")] SAMDuplicatedDest(String), - #[fail(display = "Invalid destination key: {}", _0)] + #[error("Invalid destination key: {0}")] SAMInvalidKey(String), - #[fail(display = "Invalid stream id: {}", _0)] + #[error("Invalid stream id: {0}")] SAMInvalidId(String), - #[fail(display = "I2P/SAM Timeout: {}", _0)] + #[error("I2P/SAM Timeout: {0}")] SAMTimeout(String), - #[fail(display = "Unknown I2P/SAM error: {}", _0)] + #[error("Unknown I2P/SAM error: {0}")] SAMI2PError(String), - #[fail(display = "I2P address isn't a valid b32 or b64 encoding: {}", _0)] + #[error("I2P address isn't a valid b32 or b64 encoding: {0}")] BadAddressEncoding(String), - #[fail(display = "Accept encountered error, and session was recreated. try operation again")] + #[error("Accept encountered error, and session was recreated. try operation again")] SessionRecreated, } -impl ErrorKind { - pub fn to_err(self) -> Error { - Error { - inner: Context::new(self), - } - } -} - -impl Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let cause = match self.cause() { - Some(c) => format!("{}", c), - None => String::from("Unknown"), - }; - let backtrace = match self.backtrace() { - Some(b) => format!("{}", b), - None => String::from("Unknown"), - }; - let output = format!( - "{} \n Cause: {} \n Backtrace: {}", - self.inner, cause, backtrace - ); - Display::fmt(&output, f) - } -} - -impl Error { - /// get kind - pub fn kind(&self) -> ErrorKind { - self.inner.get_context().clone() - } - /// get cause - pub fn cause(&self) -> Option<&dyn Fail> { - self.inner.cause() - } - /// get backtrace - pub fn backtrace(&self) -> Option<&Backtrace> { - self.inner.backtrace() - } -} - -impl From for Error { - fn from(kind: ErrorKind) -> Error { - Error { - inner: Context::new(kind), - } - } -} - -impl From> for Error { - fn from(inner: Context) -> Error { - Error { inner: inner } - } -} - -impl From for Error { - fn from(err: io::Error) -> Error { - Error { - inner: Context::new(ErrorKind::Io(err.to_string())), - } +impl From for I2PError { + fn from(err: io::Error) -> I2PError { + Self::Io(err.to_string()) } } -impl From> for Error { - fn from(_err: nom::Err) -> Error { - Error { - inner: Context::new(ErrorKind::MessageParsing), - } +impl From> for I2PError { + fn from(_err: nom::Err) -> I2PError { + Self::MessageParsing } } diff --git a/src/lib.rs b/src/lib.rs index 775fe1b..10b53cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,5 +6,5 @@ pub mod session_watcher; mod parsers; -pub use crate::error::{Error, ErrorKind}; +pub use crate::error::I2PError; pub use crate::sam::{SamConnection, Session}; diff --git a/src/net/addr.rs b/src/net/addr.rs index 5b88945..be6fae4 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -5,7 +5,7 @@ use std::option; use std::slice; use std::vec; -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use crate::net::i2p::I2pAddr; diff --git a/src/net/datagram.rs b/src/net/datagram.rs index 68a81c5..32d4b64 100644 --- a/src/net/datagram.rs +++ b/src/net/datagram.rs @@ -1,8 +1,8 @@ -use std::net::{SocketAddr, ToSocketAddrs}; - -use crate::error::{Error, ErrorKind}; +use crate::error::I2PError; use crate::net::{I2pSocketAddr, ToI2pSocketAddrs}; use crate::sam::DEFAULT_API; +use anyhow::Result; +use std::net::{SocketAddr, ToSocketAddrs}; /// Unimplemented /// @@ -17,7 +17,7 @@ use crate::sam::DEFAULT_API; /// use i2p::net::I2pDatagramSocket; /// use i2p::Error; /// -/// # fn foo() -> Result<(), Error> { +/// # fn foo() -> Result<()> { /// { /// let mut socket = I2pDatagramSocket::bind("127.0.0.1:34254")?; /// @@ -50,21 +50,18 @@ impl I2pDatagramSocket { /// /// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// ``` - pub fn bind(addr: A) -> Result { + pub fn bind(addr: A) -> Result { I2pDatagramSocket::bind_via(DEFAULT_API, addr) } pub fn bind_via( sam_addr: A, addr: B, - ) -> Result { + ) -> Result { super::each_i2p_addr(sam_addr, addr, I2pDatagramSocket::bind_addr).map_err(|e| e.into()) } - fn bind_addr( - _sam_addr: &SocketAddr, - _addr: &I2pSocketAddr, - ) -> Result { + fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> Result { unimplemented!(); } @@ -81,7 +78,7 @@ impl I2pDatagramSocket { /// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf) /// .expect("Didn't receive data"); /// ``` - pub fn recv_from(&self, _buf: &mut [u8]) -> Result<(usize, I2pSocketAddr), Error> { + pub fn recv_from(&self, _buf: &mut [u8]) -> Result<(usize, I2pSocketAddr)> { unimplemented!() } @@ -102,7 +99,7 @@ impl I2pDatagramSocket { /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf) /// .expect("Didn't receive data"); /// ``` - pub fn peek_from(&self, _buf: &mut [u8]) -> Result<(usize, I2pSocketAddr), Error> { + pub fn peek_from(&self, _buf: &mut [u8]) -> Result<(usize, I2pSocketAddr)> { unimplemented!() } @@ -122,10 +119,10 @@ impl I2pDatagramSocket { /// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data"); /// ``` - pub fn send_to(&self, _buf: &[u8], addr: A) -> Result { + pub fn send_to(&self, _buf: &[u8], addr: A) -> Result { match addr.to_socket_addrs()?.next() { Some(_addr) => unimplemented!(), - None => Err(ErrorKind::UnresolvableAddress.into()), + None => Err(I2PError::UnresolvableAddress.into()), } } @@ -140,7 +137,7 @@ impl I2pDatagramSocket { /// assert_eq!(socket.local_addr().unwrap(), /// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 34254)); /// ``` - pub fn local_addr(&self) -> Result { + pub fn local_addr(&self) -> Result { unimplemented!() } @@ -158,7 +155,7 @@ impl I2pDatagramSocket { /// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// let socket_clone = socket.try_clone().expect("couldn't clone the socket"); /// ``` - pub fn try_clone(&self) -> Result { + pub fn try_clone(&self) -> Result { unimplemented!() } @@ -174,7 +171,7 @@ impl I2pDatagramSocket { /// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// socket.connect("127.0.0.1:8080").expect("connect function failed"); /// ``` - pub fn connect(&self, addr: A) -> Result<(), Error> { + pub fn connect(&self, addr: A) -> Result<()> { self.connect_via(DEFAULT_API, addr) } @@ -182,7 +179,7 @@ impl I2pDatagramSocket { &self, sam_addr: A, addr: B, - ) -> Result<(), Error> { + ) -> Result<()> { super::each_i2p_addr(sam_addr, addr, |_sam_addr, _addr| unimplemented!()) } @@ -202,7 +199,7 @@ impl I2pDatagramSocket { /// socket.connect("127.0.0.1:8080").expect("connect function failed"); /// socket.send(&[0, 1, 2]).expect("couldn't send message"); /// ``` - pub fn send(&self, _buf: &[u8]) -> Result { + pub fn send(&self, _buf: &[u8]) -> Result { unimplemented!() } @@ -225,7 +222,7 @@ impl I2pDatagramSocket { /// Err(e) => println!("recv function failed: {:?}", e), /// } /// ``` - pub fn recv(&self, _buf: &mut [u8]) -> Result { + pub fn recv(&self, _buf: &mut [u8]) -> Result { unimplemented!() } @@ -253,7 +250,7 @@ impl I2pDatagramSocket { /// Err(e) => println!("peek function failed: {:?}", e), /// } /// ``` - pub fn peek(&self, _buf: &mut [u8]) -> Result { + pub fn peek(&self, _buf: &mut [u8]) -> Result { unimplemented!() } } diff --git a/src/net/i2p.rs b/src/net/i2p.rs index e15799d..2958dcc 100644 --- a/src/net/i2p.rs +++ b/src/net/i2p.rs @@ -1,12 +1,12 @@ -use std::fmt; - +use anyhow::Result; use data_encoding::{Encoding, Specification, BASE32}; use lazy_static::lazy_static; use log::error; -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; +use std::fmt; -use crate::error::{Error, ErrorKind}; +use crate::error::I2PError; pub const B32_EXT: &'static str = ".b32.i2p"; @@ -73,14 +73,14 @@ impl I2pAddr { /// Creates a new I2P address from a full base64 destination string. This /// will internally convert it to a common base32 addresse, using the /// b32.i2p extension. - pub fn from_b64(dest: &str) -> Result { + pub fn from_b64(dest: &str) -> Result { let bin_data = BASE64_I2P.decode(dest.as_bytes()).map_err(|e| { error!("Base64 decoding error: {:?}", e); - ErrorKind::BadAddressEncoding(dest.to_string()).to_err() + I2PError::BadAddressEncoding(dest.to_string()) })?; let mut hasher = Sha256::new(); hasher.input(bin_data); - let mut b32 = BASE32_I2P.encode(&hasher.result()); + let mut b32 = BASE32_I2P.encode(&hasher.result()[..]); b32.push_str(B32_EXT); Ok(I2pAddr { inner: b32 }) } diff --git a/src/net/mod.rs b/src/net/mod.rs index 4657424..29c8462 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -1,10 +1,14 @@ -use crate::error::{Error, ErrorKind}; -use std::net::{SocketAddr, ToSocketAddrs}; - pub use self::addr::{I2pSocketAddr, ToI2pSocketAddrs}; pub use self::datagram::I2pDatagramSocket; pub use self::i2p::I2pAddr; pub use self::streaming::{I2pListener, I2pStream}; +use crate::error::I2PError; +use anyhow::Result; +use std::net::{SocketAddr, ToSocketAddrs}; + +pub use self::i2p::B32_EXT; +pub use self::i2p::BASE32_I2P; +pub use self::i2p::BASE64_I2P; mod addr; mod datagram; @@ -17,9 +21,9 @@ fn each_i2p_addr( sam_addr: A, addr: B, mut f: F, -) -> Result +) -> Result where - F: FnMut(&SocketAddr, &I2pSocketAddr) -> Result, + F: FnMut(&SocketAddr, &I2pSocketAddr) -> Result, { let mut last_err = None; for addr in addr.to_socket_addrs()? { @@ -30,12 +34,12 @@ where } } } - Err(last_err.unwrap_or(ErrorKind::UnresolvableAddress.into())) + Err(last_err.unwrap_or(I2PError::UnresolvableAddress.into())) } -fn each_addr(sam_addr: A, mut f: F) -> Result +fn each_addr(sam_addr: A, mut f: F) -> Result where - F: FnMut(&SocketAddr) -> Result, + F: FnMut(&SocketAddr) -> Result, { let mut last_err = None; for sam_addr in sam_addr.to_socket_addrs()? { @@ -44,5 +48,5 @@ where Err(e) => last_err = Some(e), } } - Err(last_err.unwrap_or(ErrorKind::UnresolvableAddress.into())) + Err(last_err.unwrap_or(I2PError::UnresolvableAddress.into())) } diff --git a/src/net/streaming.rs b/src/net/streaming.rs index c451046..7ab366c 100644 --- a/src/net/streaming.rs +++ b/src/net/streaming.rs @@ -1,14 +1,14 @@ use std::io::prelude::*; +use crate::error::I2PError; +use crate::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs}; +use crate::sam::{Session, StreamConnect, StreamForward, DEFAULT_API}; +use anyhow::Result; use std::fmt; use std::io; use std::net::{Shutdown, SocketAddr, ToSocketAddrs}; use std::time::Duration; -use crate::error::{Error, ErrorKind}; -use crate::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs}; -use crate::sam::{Session, StreamConnect, StreamForward, DEFAULT_API}; - /// A structure which represents an I2P stream between a local socket and a /// remote socket. /// @@ -73,7 +73,7 @@ impl I2pStream { /// println!("Couldn't connect to server..."); /// } /// ``` - pub fn connect(addr: A) -> Result { + pub fn connect(addr: A) -> Result { I2pStream::connect_via(DEFAULT_API, addr) } @@ -81,31 +81,28 @@ impl I2pStream { pub fn connect_with_session( session: &Session, addr: A, - ) -> Result { - let addr: Result<_, Error> = addr + ) -> Result { + let addr: Result<_> = addr .to_socket_addrs()? .next() - .ok_or(ErrorKind::UnresolvableAddress.into()); + .ok_or(I2PError::UnresolvableAddress.into()); I2pStream::connect_addr_with_session(session, &addr?) } pub fn connect_via( sam_addr: A, addr: B, - ) -> Result { + ) -> Result { super::each_i2p_addr(sam_addr, addr, I2pStream::connect_addr).map_err(|e| e.into()) } - fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> Result { + fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> Result { let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port())?; Ok(I2pStream { inner: stream }) } - fn connect_addr_with_session( - session: &Session, - addr: &I2pSocketAddr, - ) -> Result { + fn connect_addr_with_session(session: &Session, addr: &I2pSocketAddr) -> Result { let stream = StreamConnect::with_session(session, &addr.dest().string(), addr.port())?; Ok(I2pStream { inner: stream }) @@ -123,7 +120,7 @@ impl I2pStream { /// assert_eq!(stream.peer_addr().unwrap(), /// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080)); /// ``` - pub fn peer_addr(&self) -> Result { + pub fn peer_addr(&self) -> Result { self.inner .peer_addr() .map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p)) @@ -141,7 +138,7 @@ impl I2pStream { /// assert_eq!(stream.local_addr().unwrap(), /// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080)); /// ``` - pub fn local_addr(&self) -> Result { + pub fn local_addr(&self) -> Result { self.inner .local_addr() .map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p)) @@ -153,7 +150,7 @@ impl I2pStream { /// successful, Ok is returned and no further action is required. If the /// IO operation could not be completed and needs to be retried, a wrapped /// Io error with kind io::ErrorKind::WouldBlock is returned. - pub fn set_nonblocking(&self, nonblocking: bool) -> Result<(), Error> { + pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> { self.inner.set_nonblocking(nonblocking) } pub fn set_read_timeout(&self, duration: Option) -> std::io::Result<()> { @@ -181,7 +178,7 @@ impl I2pStream { /// .expect("Couldn't connect to the server..."); /// stream.shutdown(Shutdown::Both).expect("shutdown call failed"); /// ``` - pub fn shutdown(&self, how: Shutdown) -> Result<(), Error> { + pub fn shutdown(&self, how: Shutdown) -> Result<()> { self.inner.shutdown(how) } @@ -201,7 +198,7 @@ impl I2pStream { /// .expect("Couldn't connect to the server..."); /// let stream_clone = stream.try_clone().expect("clone failed..."); /// ``` - pub fn try_clone(&self) -> Result { + pub fn try_clone(&self) -> Result { self.inner.duplicate().map(|s| I2pStream { inner: s }) } } @@ -285,20 +282,20 @@ impl I2pListener { /// /// let listener = I2pListener::bind().unwrap(); /// ``` - pub fn bind() -> Result { + pub fn bind() -> Result { I2pListener::bind_via(DEFAULT_API) } - pub fn bind_with_session(session: &Session) -> Result { + pub fn bind_with_session(session: &Session) -> Result { let forward = StreamForward::with_session(session)?; Ok(I2pListener { forward }) } - pub fn bind_via(sam_addr: A) -> Result { + pub fn bind_via(sam_addr: A) -> Result { super::each_addr(sam_addr, I2pListener::bind_addr).map_err(|e| e.into()) } - fn bind_addr(sam_addr: &SocketAddr) -> Result { + fn bind_addr(sam_addr: &SocketAddr) -> Result { let forward = StreamForward::new(sam_addr)?; Ok(I2pListener { forward }) } @@ -314,7 +311,7 @@ impl I2pListener { /// assert_eq!(listener.local_addr().unwrap(), /// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080)); /// ``` - pub fn local_addr(&self) -> Result { + pub fn local_addr(&self) -> Result { self.forward .local_addr() .map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p)) @@ -334,7 +331,7 @@ impl I2pListener { /// let listener = I2pListener::bind().unwrap(); /// let listener_clone = listener.try_clone().unwrap(); /// ``` - pub fn try_clone(&self) -> Result { + pub fn try_clone(&self) -> Result { let forward = self.forward.duplicate()?; Ok(I2pListener { forward }) } @@ -356,7 +353,7 @@ impl I2pListener { /// Err(e) => println!("couldn't get client: {:?}", e), /// } /// ``` - pub fn accept(&self) -> Result<(I2pStream, I2pSocketAddr), Error> { + pub fn accept(&self) -> Result<(I2pStream, I2pSocketAddr)> { let (i2p_stream, addr) = self.forward.accept()?; Ok((I2pStream { inner: i2p_stream }, addr)) } @@ -392,8 +389,8 @@ impl I2pListener { } impl<'a> Iterator for Incoming<'a> { - type Item = Result; - fn next(&mut self) -> Option> { + type Item = Result; + fn next(&mut self) -> Option> { Some(self.listener.accept().map(|p| p.0)) } } diff --git a/src/sam.rs b/src/sam.rs index 05c3ac4..04dcbbd 100644 --- a/src/sam.rs +++ b/src/sam.rs @@ -1,7 +1,7 @@ -use std::io::prelude::*; - +use anyhow::{anyhow, Context, Result}; use std::clone::Clone; use std::collections::HashMap; +use std::io::prelude::*; use std::io::{self, BufReader}; use std::net::{Shutdown, SocketAddr, TcpStream, ToSocketAddrs}; use std::time::Duration; @@ -11,7 +11,7 @@ use nom::IResult; use rand::distributions::Alphanumeric; use rand::{self, Rng}; -use crate::error::{Error, ErrorKind}; +use crate::error::I2PError; use crate::net::{I2pAddr, I2pSocketAddr}; use crate::parsers::{ sam_dest_reply, sam_hello, sam_naming_reply, sam_session_status, sam_stream_status, @@ -72,29 +72,29 @@ impl SessionStyle { } } -fn verify_response<'a>(vec: &'a [(&str, &str)]) -> Result, Error> { +fn verify_response<'a>(vec: &'a [(&str, &str)]) -> Result> { let new_vec = vec.clone(); let map: HashMap<&str, &str> = new_vec.iter().map(|&(k, v)| (k, v)).collect(); let res = map.get("RESULT").unwrap_or(&"OK").clone(); let msg = map.get("MESSAGE").unwrap_or(&"").clone(); match res { "OK" => Ok(map), - "CANT_REACH_PEER" => Err(ErrorKind::SAMCantReachPeer(msg.to_string()).into()), - "KEY_NOT_FOUND" => Err(ErrorKind::SAMKeyNotFound(msg.to_string()).into()), - "PEER_NOT_FOUND" => Err(ErrorKind::SAMPeerNotFound(msg.to_string()).into()), - "DUPLICATED_DEST" => Err(ErrorKind::SAMDuplicatedDest(msg.to_string()).into()), - "INVALID_KEY" => Err(ErrorKind::SAMInvalidKey(msg.to_string()).into()), - "INVALID_ID" => Err(ErrorKind::SAMInvalidId(msg.to_string()).into()), - "TIMEOUT" => Err(ErrorKind::SAMTimeout(msg.to_string()).into()), - "I2P_ERROR" => Err(ErrorKind::SAMI2PError(msg.to_string()).into()), - _ => Err(ErrorKind::SAMInvalidMessage(msg.to_string()).into()), + "CANT_REACH_PEER" => Err(I2PError::SAMCantReachPeer(msg.to_string()).into()), + "KEY_NOT_FOUND" => Err(I2PError::SAMKeyNotFound(msg.to_string()).into()), + "PEER_NOT_FOUND" => Err(I2PError::SAMPeerNotFound(msg.to_string()).into()), + "DUPLICATED_DEST" => Err(I2PError::SAMDuplicatedDest(msg.to_string()).into()), + "INVALID_KEY" => Err(I2PError::SAMInvalidKey(msg.to_string()).into()), + "INVALID_ID" => Err(I2PError::SAMInvalidId(msg.to_string()).into()), + "TIMEOUT" => Err(I2PError::SAMTimeout(msg.to_string()).into()), + "I2P_ERROR" => Err(I2PError::SAMI2PError(msg.to_string()).into()), + _ => Err(I2PError::SAMInvalidMessage(msg.to_string()).into()), } } impl SamConnection { - fn send(&mut self, msg: String, reply_parser: F) -> Result, Error> + pub fn send(&mut self, msg: String, mut reply_parser: F) -> Result> where - F: Fn(&str) -> IResult<&str, Vec<(&str, &str)>>, + F: FnMut(&str) -> IResult<&str, Vec<(&str, &str)>>, { debug!("-> {}", &msg); self.conn.write_all(&msg.into_bytes())?; @@ -104,7 +104,10 @@ impl SamConnection { reader.read_line(&mut buffer)?; debug!("<- {}", &buffer); - let vec_opts = reply_parser(&buffer)?.1; + // TODO: get rid of this hack + let b = string_to_static_str(buffer); + + let vec_opts = reply_parser(b)?.1; verify_response(&vec_opts).map(|m| { m.iter() .map(|(k, v)| (k.to_string(), v.to_string())) @@ -112,7 +115,7 @@ impl SamConnection { }) } - fn handshake(&mut self) -> Result, Error> { + fn handshake(&mut self) -> Result> { let hello_msg = format!( "HELLO VERSION MIN={min} MAX={max} \n", min = SAM_MIN, @@ -121,7 +124,7 @@ impl SamConnection { self.send(hello_msg, sam_hello) } - pub fn connect(addr: A) -> Result { + pub fn connect(addr: A) -> Result { let tcp_stream = TcpStream::connect(addr)?; let mut socket = SamConnection { conn: tcp_stream }; @@ -131,7 +134,7 @@ impl SamConnection { } // TODO: Implement a lookup table - pub fn naming_lookup(&mut self, name: &str) -> Result { + pub fn naming_lookup(&mut self, name: &str) -> Result { let naming_lookup_msg = format!("NAMING LOOKUP NAME={name} \n", name = name); let ret = self.send(naming_lookup_msg, sam_naming_reply)?; Ok(ret["VALUE"].clone()) @@ -140,7 +143,7 @@ impl SamConnection { pub fn generate_destination( &mut self, signature_type: SignatureType, - ) -> Result<(String, String), Error> { + ) -> Result<(String, String)> { let dest_gen_msg = format!( "DEST GENERATE SIGNATURE_TYPE={signature_type} \n", signature_type = signature_type.to_string(), @@ -149,7 +152,7 @@ impl SamConnection { Ok((ret["PUB"].clone(), ret["PRIV"].clone())) } - pub fn set_nonblocking(&self, nonblocking: bool) -> Result<(), Error> { + pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> { self.conn.set_nonblocking(nonblocking).map_err(|e| e.into()) } pub fn set_read_timeout(&self, duration: Option) -> std::io::Result<()> { @@ -158,7 +161,7 @@ impl SamConnection { pub fn set_write_timeout(&self, duration: Option) -> std::io::Result<()> { self.conn.set_write_timeout(duration) } - pub fn duplicate(&self) -> Result { + pub fn duplicate(&self) -> Result { self.conn .try_clone() .map(|s| SamConnection { conn: s }) @@ -178,7 +181,7 @@ impl Session { nickname: &str, style: SessionStyle, options: SAMOptions, - ) -> Result { + ) -> Result { let mut sam = SamConnection::connect(sam_addr)?; let create_session_msg = format!( // values for SIGNATURE_TYPE and leaseSetEncType taken from @@ -204,10 +207,7 @@ impl Session { /// Create a new session identified by the provided destination. Auto-generates /// a nickname uniquely associated with the new session. - pub fn from_destination( - sam_addr: A, - destination: &str, - ) -> Result { + pub fn from_destination(sam_addr: A, destination: &str) -> Result { Self::create( sam_addr, destination, @@ -219,7 +219,7 @@ impl Session { /// Convenience constructor to create a new transient session with an /// auto-generated nickname. - pub fn transient(sam_addr: A) -> Result { + pub fn transient(sam_addr: A) -> Result { Self::create( sam_addr, "TRANSIENT", @@ -229,15 +229,15 @@ impl Session { ) } - pub fn sam_api(&self) -> Result { + pub fn sam_api(&self) -> Result { self.sam.conn.peer_addr().map_err(|e| e.into()) } - pub fn naming_lookup(&mut self, name: &str) -> Result { + pub fn naming_lookup(&mut self, name: &str) -> Result { self.sam.naming_lookup(name) } - pub fn duplicate(&self) -> Result { + pub fn duplicate(&self) -> Result { self.sam .duplicate() .map(|s| Session { @@ -260,14 +260,14 @@ impl StreamConnect { sam_addr: A, destination: &str, port: u16, - ) -> Result { + ) -> Result { let session = Session::transient(sam_addr)?; Self::with_session(&session, destination, port) } /// Create a new SAM client connection to the provided destination and port /// using the provided session. - pub fn with_session(session: &Session, dest: &str, port: u16) -> Result { + pub fn with_session(session: &Session, dest: &str, port: u16) -> Result { let mut sam = SamConnection::connect(session.sam_api()?).unwrap(); let dest = sam.naming_lookup(dest)?; @@ -293,15 +293,15 @@ impl StreamConnect { }) } - pub fn peer_addr(&self) -> Result<(String, u16), Error> { + pub fn peer_addr(&self) -> Result<(String, u16)> { Ok((self.peer_dest.clone(), self.peer_port)) } - pub fn local_addr(&self) -> Result<(String, u16), Error> { + pub fn local_addr(&self) -> Result<(String, u16)> { Ok((self.session.local_dest.clone(), self.local_port)) } - pub fn set_nonblocking(&self, nonblocking: bool) -> Result<(), Error> { + pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> { self.sam.set_nonblocking(nonblocking) } pub fn set_read_timeout(&self, duration: Option) -> std::io::Result<()> { @@ -310,11 +310,11 @@ impl StreamConnect { pub fn set_write_timeout(&self, duration: Option) -> std::io::Result<()> { self.sam.set_write_timeout(duration) } - pub fn shutdown(&self, how: Shutdown) -> Result<(), Error> { + pub fn shutdown(&self, how: Shutdown) -> Result<()> { self.sam.conn.shutdown(how).map_err(|e| e.into()) } - pub fn duplicate(&self) -> Result { + pub fn duplicate(&self) -> Result { Ok(StreamConnect { sam: self.sam.duplicate()?, session: self.session.duplicate()?, @@ -353,7 +353,7 @@ pub struct StreamForward { } impl StreamForward { - pub fn new(sam_addr: A) -> Result { + pub fn new(sam_addr: A) -> Result { Ok(StreamForward { session: Session::transient(sam_addr)?, }) @@ -361,13 +361,13 @@ impl StreamForward { /// Create a new SAM client connection to the provided destination and port /// using the provided session. - pub fn with_session(session: &Session) -> Result { + pub fn with_session(session: &Session) -> Result { Ok(StreamForward { session: session.duplicate()?, }) } - pub fn accept(&self) -> Result<(StreamConnect, I2pSocketAddr), Error> { + pub fn accept(&self) -> Result<(StreamConnect, I2pSocketAddr)> { let mut sam_conn = SamConnection::connect(self.session.sam_api()?).unwrap(); let accept_stream_msg = format!( @@ -394,7 +394,7 @@ impl StreamForward { }; if destination.is_empty() { return Err( - ErrorKind::SAMKeyNotFound("No b64 destination in accept".to_string()).into(), + I2PError::SAMKeyNotFound("No b64 destination in accept".to_string()).into(), ); } @@ -404,11 +404,11 @@ impl StreamForward { Ok((stream, addr)) } - pub fn local_addr(&self) -> Result<(String, u16), Error> { + pub fn local_addr(&self) -> Result<(String, u16)> { Ok((self.session.local_dest.clone(), 0)) } - pub fn duplicate(&self) -> Result { + pub fn duplicate(&self) -> Result { Ok(StreamForward { session: self.session.duplicate()?, }) @@ -422,3 +422,13 @@ pub fn nickname() -> String { .collect(); format!("i2prs-{}", suffix) } + +/* +As of Rust version 1.26, it is possible to convert a String to &'static str without using unsafe code: +This converts the String instance into a boxed str and immediately leaks it. This frees all excess capacity the string may currently occupy. + +Note that there are almost always solutions that are preferable over leaking objects, e.g. using the crossbeam crate if you want to share state between threads. +*/ +fn string_to_static_str(s: String) -> &'static str { + Box::leak(s.into_boxed_str()) +} diff --git a/src/sam_options.rs b/src/sam_options.rs index fdcf4af..c3de442 100644 --- a/src/sam_options.rs +++ b/src/sam_options.rs @@ -2,8 +2,7 @@ //! I2CP client and router options taken from https://geti2p.net/en/docs/protocol/i2cp //! SAMv3 options taken from https://geti2p.net/en/docs/api/samv3#options - -use serde_derive::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; /// options used when interacting with the SAM bridge #[derive(Debug, Clone, Serialize, Deserialize)] @@ -218,18 +217,6 @@ pub enum MessageReliability { None, } -impl SignatureType { - fn string(&self) -> &str { - match self { - Self::DsaSha1 => "DSA_SHA1", - Self::EcdsaSha256P256 => "ECDSA_SHA256_P256", - Self::EcdsaSha384P384 => "ECDSA_SHA384_P384", - Self::EcdsaSha512P21 => "ECDSA_SHA512_P521", - Self::EdDsaSha512Ed25519 => "EdDSA_SHA512_Ed25519", - } - } -} - /// returns the default settings for a connection to the /// SAM bridge. Intentionally the only configured values are /// the signature type, and lease set encryption types. All other @@ -693,3 +680,19 @@ impl ToString for SignatureType { } } } + +#[cfg(test)] +mod test { + use crate::{sam::DEFAULT_API, SamConnection}; + + use super::*; + #[test] + fn test_sigs() { + let mut sam_conn = SamConnection::connect(DEFAULT_API).unwrap(); + let (pubkey, seckey) = sam_conn + .generate_destination(SignatureType::RedDsaSha512Ed25519) + .unwrap(); + println!("New public key: {}", pubkey); + println!("New secret key: {}", seckey); + } +} diff --git a/src/session_watcher.rs b/src/session_watcher.rs index 6d00c8a..11ff85b 100644 --- a/src/session_watcher.rs +++ b/src/session_watcher.rs @@ -1,98 +1,102 @@ //! provides a basic session watcher which wraps [I2pListener::accept] ensuring that //! any errors which result in the session being terminated, such as clients improperly disconnecting -//! or other network/transport level issues are handled gracefully. -//! +//! or other network/transport level issues are handled gracefully. +//! //! any calls to accept which result in an error will cause the existing session and i2plistener to be dropped, //! before they are recreated and an error is returned information the caller to try the operation again -//! - +//! +use anyhow::Result; use std::net::Shutdown; - -use crate::{sam::{StreamConnect, SessionStyle, nickname}, net::{I2pSocketAddr, I2pListener}, Session, sam_options::SAMOptions, Error, ErrorKind}; -use log::{info, warn, error}; +use crate::{ + net::{I2pListener, I2pSocketAddr}, + sam::{nickname, SessionStyle, StreamConnect}, + sam_options::SAMOptions, + I2PError, Session, +}; +use log::{error, info, warn}; /// SamSessionWatcher provides the ability to gracefully handle /// runtime errors by restarting the sam session, and recreating the listener -/// any time errors are detected. -/// -/// note: should implement better detection of which errors cause us +/// any time errors are detected. +/// +/// note: should implement better detection of which errors cause us /// to recreate the connection pub struct SamSessionWatcher { - opts: SAMOptions, - session: Session, - destination: String, - sam_endpoint: String, - session_style: SessionStyle, - pub listener: I2pListener, + opts: SAMOptions, + session: Session, + destination: String, + sam_endpoint: String, + session_style: SessionStyle, + pub listener: I2pListener, } impl SamSessionWatcher { - pub fn new( - sam_endpoint: &str, - destination: &str, - session_style: SessionStyle, - opts: SAMOptions, - ) -> Result, Error> { - let (session, listener) = SamSessionWatcher::__recreate( - sam_endpoint, - destination, - &nickname(), - session_style.clone(), - opts.clone() - )?; - Ok(Box::new(SamSessionWatcher { - opts, - session, - listener, - session_style, - destination: destination.to_string(), - sam_endpoint: sam_endpoint.to_string(), - })) - } - pub fn accept(self: &mut Box) -> Result<(StreamConnect, I2pSocketAddr), Error> { - match self.listener.forward.accept() { - Ok(res) => Ok(res), - Err(err) => { - error!("accept encountered error, recreating stream: {:#?}", err); - { - drop(&mut self.listener); - self.session.sam.conn.shutdown(Shutdown::Both)?; - drop(&mut self.session); - } - self.recreate()?; - Err(ErrorKind::SessionRecreated.into()) - } - } - } - fn recreate(self: &mut Box) -> Result<(), Error> { - let (session, listener) = SamSessionWatcher::__recreate( - &self.sam_endpoint, - &self.destination, - &nickname(), - self.session_style.clone(), - self.opts.clone() - )?; - self.session = session; - self.listener = listener; - Ok(()) - } - fn __recreate( - sam_endpoint: &str, - destination: &str, - nickname: &str, - session_style: SessionStyle, - opts: SAMOptions, - ) -> Result<(Session, I2pListener), Error> { - let session = Session::create( - sam_endpoint, - destination, - nickname, - session_style, - opts.clone(), - )?; - let listener = I2pListener::bind_with_session(&session)?; - Ok((session, listener)) - } -} \ No newline at end of file + pub fn new( + sam_endpoint: &str, + destination: &str, + session_style: SessionStyle, + opts: SAMOptions, + ) -> Result> { + let (session, listener) = SamSessionWatcher::__recreate( + sam_endpoint, + destination, + &nickname(), + session_style.clone(), + opts.clone(), + )?; + Ok(Box::new(SamSessionWatcher { + opts, + session, + listener, + session_style, + destination: destination.to_string(), + sam_endpoint: sam_endpoint.to_string(), + })) + } + pub fn accept(self: &mut Box) -> Result<(StreamConnect, I2pSocketAddr)> { + match self.listener.forward.accept() { + Ok(res) => Ok(res), + Err(err) => { + error!("accept encountered error, recreating stream: {:#?}", err); + { + drop(&mut self.listener); + self.session.sam.conn.shutdown(Shutdown::Both)?; + drop(&mut self.session); + } + self.recreate()?; + Err(I2PError::SessionRecreated.into()) + } + } + } + fn recreate(self: &mut Box) -> Result<()> { + let (session, listener) = SamSessionWatcher::__recreate( + &self.sam_endpoint, + &self.destination, + &nickname(), + self.session_style.clone(), + self.opts.clone(), + )?; + self.session = session; + self.listener = listener; + Ok(()) + } + fn __recreate( + sam_endpoint: &str, + destination: &str, + nickname: &str, + session_style: SessionStyle, + opts: SAMOptions, + ) -> Result<(Session, I2pListener)> { + let session = Session::create( + sam_endpoint, + destination, + nickname, + session_style, + opts.clone(), + )?; + let listener = I2pListener::bind_with_session(&session)?; + Ok((session, listener)) + } +} From c1344f9acd7f2fa7171d5428c3101bc047d11d33 Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:01:41 -0800 Subject: [PATCH 2/9] make all encodings public, add missing signature types --- src/net/i2p.rs | 4 ++-- src/sam_options.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/net/i2p.rs b/src/net/i2p.rs index 2958dcc..e9b2419 100644 --- a/src/net/i2p.rs +++ b/src/net/i2p.rs @@ -11,7 +11,7 @@ use crate::error::I2PError; pub const B32_EXT: &'static str = ".b32.i2p"; lazy_static! { - static ref BASE32_I2P: Encoding = { + pub static ref BASE32_I2P: Encoding = { let mut spec = Specification::new(); spec.symbols.push_str("abcdefghijklmnopqrstuvwxyz234567"); @@ -21,7 +21,7 @@ lazy_static! { } lazy_static! { - static ref BASE64_I2P: Encoding = { + pub static ref BASE64_I2P: Encoding = { let mut spec = Specification::new(); spec.symbols .push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"); diff --git a/src/sam_options.rs b/src/sam_options.rs index c3de442..f3a732e 100644 --- a/src/sam_options.rs +++ b/src/sam_options.rs @@ -207,7 +207,12 @@ pub enum SignatureType { EcdsaSha256P256, EcdsaSha384P384, EcdsaSha512P21, + RsaSha256_2048, + RsaSha384_3072, + RsaSha512_4096, EdDsaSha512Ed25519, + EdDsaSha512Ed25519ph, + RedDsaSha512Ed25519, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -676,7 +681,12 @@ impl ToString for SignatureType { Self::EcdsaSha256P256 => "ECDSA_SHA256_P256".to_string(), Self::EcdsaSha384P384 => "ECDSA_SHA384_P384".to_string(), Self::EcdsaSha512P21 => "ECDSA_SHA512_P521".to_string(), + Self::RsaSha256_2048 => "RSA_SHA256_2048".to_string(), + Self::RsaSha384_3072 => "RSA_SHA384_3072".to_string(), + Self::RsaSha512_4096 => "RSA_SHA512_4096".to_string(), Self::EdDsaSha512Ed25519 => "EdDSA_SHA512_Ed25519".to_string(), + Self::EdDsaSha512Ed25519ph => "EdDSA_SHA512_Ed25519ph".to_string(), + Self::RedDsaSha512Ed25519 => "RedDSA_SHA512_Ed25519".to_string(), } } } From da96fe32317ead677a56709f028912f8f38c2fdd Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:03:22 -0800 Subject: [PATCH 3/9] dependency updates, and utility function --- Cargo.toml | 7 ++++--- src/lib.rs | 2 ++ src/net/i2p.rs | 4 ++-- src/sam.rs | 8 +------- src/utils.rs | 4 ++++ 5 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 src/utils.rs diff --git a/Cargo.toml b/Cargo.toml index 2fc89b4..5e18947 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,11 +33,12 @@ version = "0.4" [dependencies.nom] version = "^4.2" [dependencies.rand] -version = "0.5" -[dependencies.sha2] version = "0.8" +[dependencies.sha2] +version = "0.10" [dependencies.dashmap] -dashmap = "5" +version = "5" +features = ["serde"] [dev-dependencies] env_logger = "0.5" diff --git a/src/lib.rs b/src/lib.rs index 10b53cc..c1183f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,5 +6,7 @@ pub mod session_watcher; mod parsers; +pub mod utils; + pub use crate::error::I2PError; pub use crate::sam::{SamConnection, Session}; diff --git a/src/net/i2p.rs b/src/net/i2p.rs index e9b2419..3c854cf 100644 --- a/src/net/i2p.rs +++ b/src/net/i2p.rs @@ -79,8 +79,8 @@ impl I2pAddr { I2PError::BadAddressEncoding(dest.to_string()) })?; let mut hasher = Sha256::new(); - hasher.input(bin_data); - let mut b32 = BASE32_I2P.encode(&hasher.result()[..]); + hasher.update(bin_data); + let mut b32 = BASE32_I2P.encode(&hasher.finalize()[..]); b32.push_str(B32_EXT); Ok(I2pAddr { inner: b32 }) } diff --git a/src/sam.rs b/src/sam.rs index 04dcbbd..d2e504a 100644 --- a/src/sam.rs +++ b/src/sam.rs @@ -8,8 +8,6 @@ use std::time::Duration; use log::debug; use nom::IResult; -use rand::distributions::Alphanumeric; -use rand::{self, Rng}; use crate::error::I2PError; use crate::net::{I2pAddr, I2pSocketAddr}; @@ -416,11 +414,7 @@ impl StreamForward { } pub fn nickname() -> String { - let suffix: String = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(8) - .collect(); - format!("i2prs-{}", suffix) + format!("i2prs-{}", crate::utils::rand_string(8)) } /* diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..3394adf --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,4 @@ +pub fn rand_string(length: usize) -> String { + use rand::distributions::{Alphanumeric, DistString}; + Alphanumeric.sample_string(&mut rand::thread_rng(), length) +} From 34dc5f29f158e3e355edf2ba20291f201144e606 Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:06:20 -0800 Subject: [PATCH 4/9] update nom to v5 --- Cargo.toml | 2 +- src/error.rs | 4 ++-- src/parsers.rs | 53 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5e18947..0b4f83c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ version = "1" [dependencies.log] version = "0.4" [dependencies.nom] -version = "^4.2" +version = "5" [dependencies.rand] version = "0.8" [dependencies.sha2] diff --git a/src/error.rs b/src/error.rs index 96806b3..4e3479e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -44,8 +44,8 @@ impl From for I2PError { } } -impl From> for I2PError { - fn from(_err: nom::Err) -> I2PError { +impl From> for I2PError { + fn from(_err: nom::Err) -> I2PError { Self::MessageParsing } } diff --git a/src/parsers.rs b/src/parsers.rs index cee6220..c1cd773 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -1,5 +1,7 @@ -use nom::{alphanumeric, alt, do_parse, named, separated_list, space, tag, take_till}; - +use nom::{ + alt, do_parse, named, separated_list, tag, take_till, + character::complete::{alphanumeric1 as alphanumeric, space1 as space}, +}; fn is_space(chr: char) -> bool { chr == ' ' || chr == '\t' } @@ -85,7 +87,7 @@ named!(pub sam_dest_reply <&str, Vec<(&str, &str)> >, #[cfg(test)] mod tests { - use nom::ErrorKind; + use nom::error::ErrorKind; #[test] fn hello() { @@ -158,20 +160,37 @@ mod tests { assert_eq!( sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"), Ok(("", vec![("RESULT", "KEY_NOT_FOUND")])) - ); - - assert_eq!( - sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n") - .unwrap_err() - .into_error_kind(), - ErrorKind::Tag - ); - assert_eq!( - sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n") - .unwrap_err() - .into_error_kind(), - ErrorKind::Tag - ); + ); + if let Err(err) = sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n") { + match err { + nom::Err::Error((_, e)) => { + assert_eq!(e, ErrorKind::Tag); + } + nom::Err::Failure((_, e)) => { + assert_eq!(e, ErrorKind::Tag); + } + nom::Err::Incomplete(e) => { + panic!("unepxected error"); + } + } + } else { + panic!("expected error"); + } + if let Err(err) = sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n") { + match err { + nom::Err::Error((_, e)) => { + assert_eq!(e, ErrorKind::Tag); + } + nom::Err::Failure((_, e)) => { + assert_eq!(e, ErrorKind::Tag); + } + nom::Err::Incomplete(e) => { + panic!("unepxected error"); + } + } + } else { + panic!("expected error"); + } } #[test] From 3fe432b35d844f5e7453458f899ebe7f9096dada Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:07:44 -0800 Subject: [PATCH 5/9] another nom update --- Cargo.toml | 2 +- src/parsers.rs | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0b4f83c..9fd961b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ version = "1" [dependencies.log] version = "0.4" [dependencies.nom] -version = "5" +version = "6" [dependencies.rand] version = "0.8" [dependencies.sha2] diff --git a/src/parsers.rs b/src/parsers.rs index c1cd773..bfc1a63 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -1,6 +1,7 @@ use nom::{ alt, do_parse, named, separated_list, tag, take_till, character::complete::{alphanumeric1 as alphanumeric, space1 as space}, + do_parse, named, separated_list0, tag, take_till, }; fn is_space(chr: char) -> bool { chr == ' ' || chr == '\t' @@ -38,7 +39,7 @@ named!(key_value <&str, (&str, &str)>, ) ); -named!(keys_and_values<&str, Vec<(&str, &str)> >, separated_list!(space, key_value)); +named!(keys_and_values<&str, Vec<(&str, &str)> >, separated_list0!(space, key_value)); named!(pub sam_hello <&str, Vec<(&str, &str)> >, do_parse!( @@ -163,11 +164,11 @@ mod tests { ); if let Err(err) = sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n") { match err { - nom::Err::Error((_, e)) => { - assert_eq!(e, ErrorKind::Tag); - } - nom::Err::Failure((_, e)) => { - assert_eq!(e, ErrorKind::Tag); + nom::Err::Error(err) => { + assert_eq!(err.code, ErrorKind::Tag); + } + nom::Err::Failure(err) => { + assert_eq!(err.code, ErrorKind::Tag); } nom::Err::Incomplete(e) => { panic!("unepxected error"); @@ -178,11 +179,11 @@ mod tests { } if let Err(err) = sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n") { match err { - nom::Err::Error((_, e)) => { - assert_eq!(e, ErrorKind::Tag); - } - nom::Err::Failure((_, e)) => { - assert_eq!(e, ErrorKind::Tag); + nom::Err::Error(err) => { + assert_eq!(err.code, ErrorKind::Tag); + } + nom::Err::Failure(err) => { + assert_eq!(err.code, ErrorKind::Tag); } nom::Err::Incomplete(e) => { panic!("unepxected error"); From 61984b65f7f64eb1078fed5dbd934e5c20ffb824 Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:28:13 -0800 Subject: [PATCH 6/9] lints, formats, code cleanup --- src/error.rs | 2 +- src/net/addr.rs | 39 +++++++---------- src/net/datagram.rs | 2 +- src/net/i2p.rs | 4 +- src/net/streaming.rs | 4 +- src/parsers.rs | 8 ++-- src/sam.rs | 48 +++++++++------------ src/sam_options.rs | 98 +++++++++++++++++++++--------------------- src/session_watcher.rs | 12 +----- tests/naming_lookup.rs | 2 +- 10 files changed, 96 insertions(+), 123 deletions(-) diff --git a/src/error.rs b/src/error.rs index 4e3479e..ed4df00 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,5 @@ use nom; -use std::fmt::{self, Display}; + use std::io; use thiserror::Error as ThisError; diff --git a/src/net/addr.rs b/src/net/addr.rs index be6fae4..06c6c6b 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -28,10 +28,7 @@ impl I2pSocketAddr { /// assert_eq!(socket.port(), 8080); /// ``` pub fn new(dest: I2pAddr, port: u16) -> I2pSocketAddr { - I2pSocketAddr { - port: port, - dest: dest, - } + I2pSocketAddr { port, dest } } /// Returns the I2P address associated with this socket address. @@ -134,23 +131,17 @@ impl fmt::Display for I2pSocketAddr { /// ```no_run /// use i2p::net::{I2pSocketAddr, I2pStream, I2pDatagramSocket, I2pListener, I2pAddr}; /// -/// fn main() { -/// let dest = I2pAddr::new("example.i2p"); -/// let port = 12345; -/// -/// // The following lines are equivalent -/// let i2p_s = I2pStream::connect(I2pSocketAddr::new(dest.clone(), port)); -/// let i2p_s = I2pStream::connect((dest.clone(), port)); -/// let i2p_s = I2pStream::connect(("example.i2p", port)); -/// let i2p_s = I2pStream::connect("example.i2p:12345"); -/// -/// // I2pListener::bind(), I2pDatagramSocket::bind() and I2pDatagramSocket::send_to() -/// // behave similarly -/// let i2p_l = I2pListener::bind(); -/// -/// let mut i2p_dg_s = I2pDatagramSocket::bind(("127.0.0.1", port)).unwrap(); -/// i2p_dg_s.send_to(&[7], (dest, 23451)).unwrap(); -/// } +/// let dest = I2pAddr::new("example.i2p"); +/// let port = 12345; +/// The following lines are equivalent +/// let i2p_s = I2pStream::connect(I2pSocketAddr::new(dest.clone(), port)); +/// let i2p_s = I2pStream::connect((dest.clone(), port)); +/// let i2p_s = I2pStream::connect(("example.i2p", port)); +/// let i2p_s = I2pStream::connect("example.i2p:12345"); +/// // I2pListener::bind(), I2pDatagramSocket::bind() and I2pDatagramSocket::send_to() behave similarly +/// let i2p_l = I2pListener::bind(); +/// let mut i2p_dg_s = I2pDatagramSocket::bind(("127.0.0.1", port)).unwrap(); +/// i2p_dg_s.send_to(&[7], (dest, 23451)).unwrap(); /// ``` pub trait ToI2pSocketAddrs { /// Returned iterator over socket addresses which this type may correspond @@ -235,7 +226,7 @@ impl<'a, T: ToI2pSocketAddrs + ?Sized> ToI2pSocketAddrs for &'a T { impl ToI2pSocketAddrs for String { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { - (&**self).to_socket_addrs() + (**self).to_socket_addrs() } } @@ -279,7 +270,7 @@ mod tests { ); assert_eq!( Ok(vec![a.clone()]), - tsa(&format!("{}:{}", "example.i2p", "24352")) + tsa(format!("{}:{}", "example.i2p", "24352")) ); assert_eq!( Ok(vec![a.clone()]), @@ -294,7 +285,7 @@ mod tests { #[test] fn set_dest() { fn i2p(low: u8) -> I2pAddr { - I2pAddr::new(&format!("example{}.i2p", low)) + I2pAddr::new(&format!("example{low}.i2p")) } let mut addr = I2pSocketAddr::new(i2p(12), 80); diff --git a/src/net/datagram.rs b/src/net/datagram.rs index 32d4b64..5537cb4 100644 --- a/src/net/datagram.rs +++ b/src/net/datagram.rs @@ -58,7 +58,7 @@ impl I2pDatagramSocket { sam_addr: A, addr: B, ) -> Result { - super::each_i2p_addr(sam_addr, addr, I2pDatagramSocket::bind_addr).map_err(|e| e.into()) + super::each_i2p_addr(sam_addr, addr, I2pDatagramSocket::bind_addr) } fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> Result { diff --git a/src/net/i2p.rs b/src/net/i2p.rs index 3c854cf..b7d7717 100644 --- a/src/net/i2p.rs +++ b/src/net/i2p.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use data_encoding::{Encoding, Specification, BASE32}; +use data_encoding::{Encoding, Specification}; use lazy_static::lazy_static; use log::error; use serde::{Deserialize, Serialize}; @@ -8,7 +8,7 @@ use std::fmt; use crate::error::I2PError; -pub const B32_EXT: &'static str = ".b32.i2p"; +pub const B32_EXT: &str = ".b32.i2p"; lazy_static! { pub static ref BASE32_I2P: Encoding = { diff --git a/src/net/streaming.rs b/src/net/streaming.rs index 7ab366c..4f3d3b9 100644 --- a/src/net/streaming.rs +++ b/src/net/streaming.rs @@ -93,7 +93,7 @@ impl I2pStream { sam_addr: A, addr: B, ) -> Result { - super::each_i2p_addr(sam_addr, addr, I2pStream::connect_addr).map_err(|e| e.into()) + super::each_i2p_addr(sam_addr, addr, I2pStream::connect_addr) } fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> Result { @@ -292,7 +292,7 @@ impl I2pListener { } pub fn bind_via(sam_addr: A) -> Result { - super::each_addr(sam_addr, I2pListener::bind_addr).map_err(|e| e.into()) + super::each_addr(sam_addr, I2pListener::bind_addr) } fn bind_addr(sam_addr: &SocketAddr) -> Result { diff --git a/src/parsers.rs b/src/parsers.rs index bfc1a63..2ab2079 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -1,5 +1,5 @@ use nom::{ - alt, do_parse, named, separated_list, tag, take_till, + alt, character::complete::{alphanumeric1 as alphanumeric, space1 as space}, do_parse, named, separated_list0, tag, take_till, }; @@ -161,7 +161,7 @@ mod tests { assert_eq!( sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"), Ok(("", vec![("RESULT", "KEY_NOT_FOUND")])) - ); + ); if let Err(err) = sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n") { match err { nom::Err::Error(err) => { @@ -170,7 +170,7 @@ mod tests { nom::Err::Failure(err) => { assert_eq!(err.code, ErrorKind::Tag); } - nom::Err::Incomplete(e) => { + nom::Err::Incomplete(_e) => { panic!("unepxected error"); } } @@ -185,7 +185,7 @@ mod tests { nom::Err::Failure(err) => { assert_eq!(err.code, ErrorKind::Tag); } - nom::Err::Incomplete(e) => { + nom::Err::Incomplete(_e) => { panic!("unepxected error"); } } diff --git a/src/sam.rs b/src/sam.rs index d2e504a..9bf8e78 100644 --- a/src/sam.rs +++ b/src/sam.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Context, Result}; +use anyhow::Result; use std::clone::Clone; use std::collections::HashMap; use std::io::prelude::*; @@ -16,10 +16,10 @@ use crate::parsers::{ }; use crate::sam_options::{SAMOptions, SignatureType}; -pub static DEFAULT_API: &'static str = "127.0.0.1:7656"; +pub static DEFAULT_API: &str = "127.0.0.1:7656"; -static SAM_MIN: &'static str = "3.0"; -static SAM_MAX: &'static str = "3.2"; +static SAM_MIN: &str = "3.0"; +static SAM_MAX: &str = "3.2"; #[derive(Clone, Debug)] pub enum SessionStyle { @@ -71,10 +71,9 @@ impl SessionStyle { } fn verify_response<'a>(vec: &'a [(&str, &str)]) -> Result> { - let new_vec = vec.clone(); - let map: HashMap<&str, &str> = new_vec.iter().map(|&(k, v)| (k, v)).collect(); - let res = map.get("RESULT").unwrap_or(&"OK").clone(); - let msg = map.get("MESSAGE").unwrap_or(&"").clone(); + let map: HashMap<&str, &str> = vec.iter().copied().collect(); + let res = <&str>::clone(map.get("RESULT").unwrap_or(&"OK")); + let msg = <&str>::clone(map.get("MESSAGE").unwrap_or(&"")); match res { "OK" => Ok(map), "CANT_REACH_PEER" => Err(I2PError::SAMCantReachPeer(msg.to_string()).into()), @@ -114,11 +113,7 @@ impl SamConnection { } fn handshake(&mut self) -> Result> { - let hello_msg = format!( - "HELLO VERSION MIN={min} MAX={max} \n", - min = SAM_MIN, - max = SAM_MAX - ); + let hello_msg = format!("HELLO VERSION MIN={SAM_MIN} MAX={SAM_MAX} \n"); self.send(hello_msg, sam_hello) } @@ -133,7 +128,7 @@ impl SamConnection { // TODO: Implement a lookup table pub fn naming_lookup(&mut self, name: &str) -> Result { - let naming_lookup_msg = format!("NAMING LOOKUP NAME={name} \n", name = name); + let naming_lookup_msg = format!("NAMING LOOKUP NAME={name} \n"); let ret = self.send(naming_lookup_msg, sam_naming_reply)?; Ok(ret["VALUE"].clone()) } @@ -197,8 +192,8 @@ impl Session { let local_dest = sam.naming_lookup("ME")?; Ok(Session { - sam: sam, - local_dest: local_dest, + sam, + local_dest, nickname: nickname.to_string(), }) } @@ -236,14 +231,11 @@ impl Session { } pub fn duplicate(&self) -> Result { - self.sam - .duplicate() - .map(|s| Session { - sam: s, - local_dest: self.local_dest.clone(), - nickname: self.nickname.clone(), - }) - .map_err(|e| e.into()) + self.sam.duplicate().map(|s| Session { + sam: s, + local_dest: self.local_dest.clone(), + nickname: self.nickname.clone(), + }) } /// attempts to return a handle to the underlying socket pub fn try_clone(&self) -> std::io::Result { @@ -275,15 +267,15 @@ impl StreamConnect { destination = dest, ); if port > 0 { - stream_msg.push_str(&format!(" TO_PORT={port}\n", port = port)); + stream_msg.push_str(&format!(" TO_PORT={port}\n")); } else { - stream_msg.push_str("\n"); + stream_msg.push('\n'); } sam.send(stream_msg, sam_stream_status)?; Ok(StreamConnect { - sam: sam, + sam, session: session.duplicate()?, peer_dest: dest, peer_port: port, @@ -388,7 +380,7 @@ impl StreamForward { let mut buf_read = io::BufReader::new(stream.duplicate()?); let mut dest_line = String::new(); buf_read.read_line(&mut dest_line)?; - dest_line.split(" ").next().unwrap_or("").trim().to_string() + dest_line.split(' ').next().unwrap_or("").trim().to_string() }; if destination.is_empty() { return Err( diff --git a/src/sam_options.rs b/src/sam_options.rs index f3a732e..48a11b8 100644 --- a/src/sam_options.rs +++ b/src/sam_options.rs @@ -263,13 +263,13 @@ impl I2CPOptions { let mut options = String::default(); if let Some(router_options) = &self.router_options { let router_options_str = router_options.string(); - if router_options_str != "" { + if !router_options_str.is_empty() { options.push_str(router_options_str.as_str()); } } if let Some(client_options) = &self.client_options { let client_options_str = client_options.string(); - if client_options_str != "" { + if !client_options_str.is_empty() { options.push_str(client_options_str.as_str()); } } @@ -281,22 +281,21 @@ impl I2CPRouterOptions { pub fn string(&self) -> String { let mut options = String::default(); if let Some(client_message_timeout) = &self.client_message_timeout { - options.push_str(&format!("clientMessageTimeout={} ", client_message_timeout)); + options.push_str(&format!("clientMessageTimeout={client_message_timeout} ")); } if let Some(crypto_options) = &self.crypto_options { let crypto_options_str = crypto_options.string(); - if crypto_options_str != "" { - options.push_str(&crypto_options_str.as_str()); + if !crypto_options_str.is_empty() { + options.push_str(crypto_options_str.as_str()); } } if let Some(dont_publish_lease_set) = &self.dont_publish_lease_set { options.push_str(&format!( - "i2cp.dontPublishLeaseSet={} ", - dont_publish_lease_set + "i2cp.dontPublishLeaseSet={dont_publish_lease_set} " )); } if let Some(fast_receive) = &self.fast_receive { - options.push_str(&format!("i2cp.fastReceive={} ", fast_receive)); + options.push_str(&format!("i2cp.fastReceive={fast_receive} ")); } if let Some(lease_set_auth_type) = &self.lease_set_auth_type { options.push_str(&format!( @@ -347,27 +346,26 @@ impl I2CPRouterOptions { )); } if let Some(password) = &self.password { - options.push_str(&format!("i2cp.password={} ", password)); + options.push_str(&format!("i2cp.password={password} ")); } if let Some(username) = &self.username { - options.push_str(&format!("i2cp.username={} ", username)); + options.push_str(&format!("i2cp.username={username} ")); } if let Some(inbound) = &self.inbound { let inbound_str = inbound.string(); - if inbound_str != "" { + if !inbound_str.is_empty() { options.push_str(inbound_str.as_str()); } } if let Some(outbound) = &self.outbound { let outbound_str = outbound.string(); - if outbound_str != "" { + if !outbound_str.is_empty() { options.push_str(outbound_str.as_str()); } } if let Some(should_bundle_reply_info) = &self.should_bundle_reply_info { options.push_str(&format!( - "shouldBundleReplyInfo={} ", - should_bundle_reply_info + "shouldBundleReplyInfo={should_bundle_reply_info} " )); } options @@ -378,19 +376,19 @@ impl I2CPClientOptions { pub fn string(&self) -> String { let mut options = String::default(); if let Some(close_idle_time) = &self.close_idle_time { - options.push_str(&format!("i2cp.closeIdleTime={} ", close_idle_time)); + options.push_str(&format!("i2cp.closeIdleTime={close_idle_time} ")); } if let Some(close_on_idle) = &self.close_on_idle { - options.push_str(&format!("i2cp.closeOnIdle={} ", close_on_idle)); + options.push_str(&format!("i2cp.closeOnIdle={close_on_idle} ")); } if let Some(encrypt_lease_set) = &self.encrypt_lease_set { - options.push_str(&format!("i2cp.encryptLeaseSet={} ", encrypt_lease_set)); + options.push_str(&format!("i2cp.encryptLeaseSet={encrypt_lease_set} ")); } if let Some(fast_receive) = &self.fast_receive { - options.push_str(&format!("i2cp.fastReceive={} ", fast_receive)); + options.push_str(&format!("i2cp.fastReceive={fast_receive} ")); } if let Some(gzip) = &self.gzip { - options.push_str(&format!("i2cp.gzip={} ", gzip)); + options.push_str(&format!("i2cp.gzip={gzip} ")); } if let Some(lease_set_auth_type) = &self.lease_set_auth_type { options.push_str(&format!( @@ -438,19 +436,19 @@ impl I2CPClientOptions { )); } if let Some(reduce_idle_time) = &self.reduce_idle_time { - options.push_str(&format!("i2cp.reduceIdleTime={} ", reduce_idle_time)); + options.push_str(&format!("i2cp.reduceIdleTime={reduce_idle_time} ")); } if let Some(reduce_on_idle) = &self.reduce_on_idle { - options.push_str(&format!("i2cp.reduceOnIdle={} ", reduce_on_idle)); + options.push_str(&format!("i2cp.reduceOnIdle={reduce_on_idle} ")); } if let Some(ssl) = &self.ssl { - options.push_str(&format!("i2cp.ssl={} ", ssl)); + options.push_str(&format!("i2cp.ssl={ssl} ")); } if let Some(tcp_host) = &self.tcp_host { - options.push_str(&format!("i2cp.tcp.host={} ", tcp_host)); + options.push_str(&format!("i2cp.tcp.host={tcp_host} ")); } if let Some(tcp_port) = &self.tcp_port { - options.push_str(&format!("i2cp.tcp.port={} ", tcp_port)); + options.push_str(&format!("i2cp.tcp.port={tcp_port} ")); } options } @@ -460,16 +458,16 @@ impl I2CPRouterCryptoOptions { pub fn string(&self) -> String { let mut options = String::default(); if let Some(low_tag_threshold) = &self.low_tag_threshold { - options.push_str(&format!("crypto.lowTagThreshold={} ", low_tag_threshold)); + options.push_str(&format!("crypto.lowTagThreshold={low_tag_threshold} ")); } if let Some(inbound_tags) = &self.ratchet_inbound_tags { - options.push_str(&format!("crypto.ratchet.inboundTags={} ", inbound_tags)); + options.push_str(&format!("crypto.ratchet.inboundTags={inbound_tags} ")); } if let Some(outbound_tags) = &self.ratchet_outbound_tags { - options.push_str(&format!("crypto.ratchet.outboundTags={} ", outbound_tags)); + options.push_str(&format!("crypto.ratchet.outboundTags={outbound_tags} ")); } if let Some(tags_to_send) = &self.tags_to_send { - options.push_str(&format!("crypto.tagsToSend={} ", tags_to_send)); + options.push_str(&format!("crypto.tagsToSend={tags_to_send} ")); } options } @@ -479,25 +477,25 @@ impl I2CPTunnelInboundOptions { pub fn string(&self) -> String { let mut options = String::default(); if let Some(allow_zero_hop) = &self.allow_zero_hop { - options.push_str(&format!("inbound.allowZeroHop={} ", allow_zero_hop)); + options.push_str(&format!("inbound.allowZeroHop={allow_zero_hop} ")); } if let Some(backup_quantity) = &self.backup_quantity { - options.push_str(&format!("inbound.backupQuantity={} ", backup_quantity)); + options.push_str(&format!("inbound.backupQuantity={backup_quantity} ")); } if let Some(ip_restriction) = &self.ip_restriction { - options.push_str(&format!("inbound.IPRestriction={} ", ip_restriction)); + options.push_str(&format!("inbound.IPRestriction={ip_restriction} ")); } if let Some(length) = &self.length { - options.push_str(&format!("inbound.length={} ", length)); + options.push_str(&format!("inbound.length={length} ")); } if let Some(length_variance) = &self.length_variance { - options.push_str(&format!("inbound.lengthVariance{} ", length_variance)); + options.push_str(&format!("inbound.lengthVariance{length_variance} ")); } if let Some(quantity) = &self.quantity { - options.push_str(&format!("inbound.quantity={} ", quantity)); + options.push_str(&format!("inbound.quantity={quantity} ")); } if let Some(random_key) = &self.random_key { - options.push_str(&format!("inbound.randomKey={} ", random_key)); + options.push_str(&format!("inbound.randomKey={random_key} ")); } options } @@ -507,28 +505,28 @@ impl I2CPTunnelOutboundOptions { pub fn string(&self) -> String { let mut options = String::default(); if let Some(allow_zero_hop) = &self.allow_zero_hop { - options.push_str(&format!("outbound.allowZeroHop={} ", allow_zero_hop)); + options.push_str(&format!("outbound.allowZeroHop={allow_zero_hop} ")); } if let Some(backup_quantity) = &self.backup_quantity { - options.push_str(&format!("outbound.backupQuantity={} ", backup_quantity)); + options.push_str(&format!("outbound.backupQuantity={backup_quantity} ")); } if let Some(ip_restriction) = &self.ip_restriction { - options.push_str(&format!("outbound.IPRestriction={} ", ip_restriction)); + options.push_str(&format!("outbound.IPRestriction={ip_restriction} ")); } if let Some(length) = &self.length { - options.push_str(&format!("outbound.length={} ", length)); + options.push_str(&format!("outbound.length={length} ")); } if let Some(length_variance) = &self.length_variance { - options.push_str(&format!("outbound.lengthVariance{} ", length_variance)); + options.push_str(&format!("outbound.lengthVariance{length_variance} ")); } if let Some(priority) = &self.priority { - options.push_str(&format!("outbound.priority={} ", priority)); + options.push_str(&format!("outbound.priority={priority} ")); } if let Some(quantity) = &self.quantity { - options.push_str(&format!("outbound.quantity={} ", quantity)); + options.push_str(&format!("outbound.quantity={quantity} ")); } if let Some(random_key) = &self.random_key { - options.push_str(&format!("outbound.randomKey={} ", random_key)); + options.push_str(&format!("outbound.randomKey={random_key} ")); } options } @@ -650,25 +648,25 @@ impl ToString for SAMOptions { fn to_string(&self) -> String { let mut options = String::default(); if let Some(from_port) = &self.from_port { - options.push_str(&format!("FROM_PORT={} ", from_port)); + options.push_str(&format!("FROM_PORT={from_port} ")); } if let Some(to_port) = &self.to_port { - options.push_str(&format!("TO_PORT={} ", to_port)); + options.push_str(&format!("TO_PORT={to_port} ")); } if let Some(i2cp_options) = &self.i2cp_options { let i2cp_options_str = i2cp_options.string(); - if i2cp_options_str != "" { + if !i2cp_options_str.is_empty() { options.push_str(i2cp_options_str.as_str()); } } // make sure to remove duplicate options // todo: there is likely a better way of handling this - let mut options_parts: Vec<_> = options.split(" ").collect(); + let mut options_parts: Vec<_> = options.split(' ').collect(); options_parts.sort_unstable(); options_parts.dedup(); let mut options_parsed = String::default(); for option_part in options_parts.clone() { - options_parsed.push_str(&format!("{} ", option_part)); + options_parsed.push_str(&format!("{option_part} ")); } options_parsed } @@ -702,7 +700,7 @@ mod test { let (pubkey, seckey) = sam_conn .generate_destination(SignatureType::RedDsaSha512Ed25519) .unwrap(); - println!("New public key: {}", pubkey); - println!("New secret key: {}", seckey); + println!("New public key: {pubkey}"); + println!("New secret key: {seckey}"); } } diff --git a/src/session_watcher.rs b/src/session_watcher.rs index 11ff85b..86f46f1 100644 --- a/src/session_watcher.rs +++ b/src/session_watcher.rs @@ -15,7 +15,7 @@ use crate::{ sam_options::SAMOptions, I2PError, Session, }; -use log::{error, info, warn}; +use log::error; /// SamSessionWatcher provides the ability to gracefully handle /// runtime errors by restarting the sam session, and recreating the listener @@ -61,9 +61,7 @@ impl SamSessionWatcher { Err(err) => { error!("accept encountered error, recreating stream: {:#?}", err); { - drop(&mut self.listener); self.session.sam.conn.shutdown(Shutdown::Both)?; - drop(&mut self.session); } self.recreate()?; Err(I2PError::SessionRecreated.into()) @@ -89,13 +87,7 @@ impl SamSessionWatcher { session_style: SessionStyle, opts: SAMOptions, ) -> Result<(Session, I2pListener)> { - let session = Session::create( - sam_endpoint, - destination, - nickname, - session_style, - opts.clone(), - )?; + let session = Session::create(sam_endpoint, destination, nickname, session_style, opts)?; let listener = I2pListener::bind_with_session(&session)?; Ok((session, listener)) } diff --git a/tests/naming_lookup.rs b/tests/naming_lookup.rs index 94910f2..2f393a8 100644 --- a/tests/naming_lookup.rs +++ b/tests/naming_lookup.rs @@ -12,7 +12,7 @@ fn naming_lookup() { "GKapJ8koUcBj~jmQzHsTYxDg2tpfWj0xjQTzd8BhfC9c3OS5fwPBNajgF-eOD6eCjFTqTlorlh7Hnd8kXj1qblUGXT-tDoR9~YV8dmXl51cJn9MVTRrEqRWSJVXbUUz9t5Po6Xa247Vr0sJn27R4KoKP8QVj1GuH6dB3b6wTPbOamC3dkO18vkQkfZWUdRMDXk0d8AdjB0E0864nOT~J9Fpnd2pQE5uoFT6P0DqtQR2jsFvf9ME61aqLvKPPWpkgdn4z6Zkm-NJOcDz2Nv8Si7hli94E9SghMYRsdjU-knObKvxiagn84FIwcOpepxuG~kFXdD5NfsH0v6Uri3usE3XWD7Pw6P8qVYF39jUIq4OiNMwPnNYzy2N4mDMQdsdHO3LUVh~DEppOy9AAmEoHDjjJxt2BFBbGxfdpZCpENkwvmZeYUyNCCzASqTOOlNzdpne8cuesn3NDXIpNnqEE6Oe5Qm5YOJykrX~Vx~cFFT3QzDGkIjjxlFBsjUJyYkFjBQAEAAcAAA==" ) } - Err(ref e) => panic!("An error occurred: {}", e), + Err(ref e) => panic!("An error occurred: {e}"), } } } From 0d1f116dbcd38c26602da802a8e7b796871ae7ae Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:30:11 -0800 Subject: [PATCH 7/9] remove unused dependency --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9fd961b..35df362 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,9 +36,5 @@ version = "6" version = "0.8" [dependencies.sha2] version = "0.10" -[dependencies.dashmap] -version = "5" -features = ["serde"] - [dev-dependencies] env_logger = "0.5" From f1bab60744e6532be1a1359f02c4f11adb01fc35 Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:31:39 -0800 Subject: [PATCH 8/9] update repo version --- Cargo.toml | 2 +- examples/eepget/Cargo.toml | 2 +- examples/gen_dest/Cargo.toml | 2 +- examples/hello_world/Cargo.toml | 2 +- examples/selfserve/Cargo.toml | 2 +- examples/session_watcher/Cargo.toml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 35df362..feed126 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "i2p" -version = "0.1.1" +version = "0.2.0" authors = ["Jack Grigg "] description = "I2P client library with a std::net-like API" homepage = "https://github.com/i2p/i2p-rs" diff --git a/examples/eepget/Cargo.toml b/examples/eepget/Cargo.toml index a26e3d3..2c4d823 100644 --- a/examples/eepget/Cargo.toml +++ b/examples/eepget/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -i2p = {path = "../../", version = "0.1.0"} +i2p = {path = "../../", version = "0.2.0"} env_logger = "0.5" [[bin]] diff --git a/examples/gen_dest/Cargo.toml b/examples/gen_dest/Cargo.toml index a416053..408a757 100644 --- a/examples/gen_dest/Cargo.toml +++ b/examples/gen_dest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -i2p = {path = "../../", version = "0.1.0"} +i2p = {path = "../../", version = "0.2.0"} env_logger = "0.5" [[bin]] diff --git a/examples/hello_world/Cargo.toml b/examples/hello_world/Cargo.toml index 06e7bdb..5aaf8c6 100644 --- a/examples/hello_world/Cargo.toml +++ b/examples/hello_world/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -i2p = {path = "../../", version = "0.1.0"} +i2p = {path = "../../", version = "0.2.0"} env_logger = "0.5" log = "0.4" crossbeam = "0.8" diff --git a/examples/selfserve/Cargo.toml b/examples/selfserve/Cargo.toml index 0e121df..c91797d 100644 --- a/examples/selfserve/Cargo.toml +++ b/examples/selfserve/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -i2p = {path = "../../", version = "0.1.0"} +i2p = {path = "../../", version = "0.2.0"} env_logger = "0.5" log = "0.4.6" diff --git a/examples/session_watcher/Cargo.toml b/examples/session_watcher/Cargo.toml index db62ee3..0546178 100644 --- a/examples/session_watcher/Cargo.toml +++ b/examples/session_watcher/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -i2p = {path = "../../", version = "0.1.0"} +i2p = {path = "../../", version = "0.2.0"} env_logger = "0.5" log = "0.4" crossbeam = "0.8" From 7e8e94fe3a7966629d8f10af189d28c93c207f4b Mon Sep 17 00:00:00 2001 From: bonedaddy Date: Wed, 18 Jan 2023 18:37:25 -0800 Subject: [PATCH 9/9] last round of lints, and fixes to get tests working --- src/net/addr.rs | 27 ++++++++++++++------------- src/net/datagram.rs | 32 +++++++++++++++----------------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/net/addr.rs b/src/net/addr.rs index 06c6c6b..8cc6f16 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -129,19 +129,20 @@ impl fmt::Display for I2pSocketAddr { /// Some examples: /// /// ```no_run -/// use i2p::net::{I2pSocketAddr, I2pStream, I2pDatagramSocket, I2pListener, I2pAddr}; -/// -/// let dest = I2pAddr::new("example.i2p"); -/// let port = 12345; -/// The following lines are equivalent -/// let i2p_s = I2pStream::connect(I2pSocketAddr::new(dest.clone(), port)); -/// let i2p_s = I2pStream::connect((dest.clone(), port)); -/// let i2p_s = I2pStream::connect(("example.i2p", port)); -/// let i2p_s = I2pStream::connect("example.i2p:12345"); -/// // I2pListener::bind(), I2pDatagramSocket::bind() and I2pDatagramSocket::send_to() behave similarly -/// let i2p_l = I2pListener::bind(); -/// let mut i2p_dg_s = I2pDatagramSocket::bind(("127.0.0.1", port)).unwrap(); -/// i2p_dg_s.send_to(&[7], (dest, 23451)).unwrap(); +/// fn execute() { +/// use i2p::net::{I2pSocketAddr, I2pStream, I2pDatagramSocket, I2pListener, I2pAddr}; +/// let dest = I2pAddr::new("example.i2p"); +/// let port = 12345; +/// // The following lines are equivalent +/// let i2p_s = I2pStream::connect(I2pSocketAddr::new(dest.clone(), port)); +/// let i2p_s = I2pStream::connect((dest.clone(), port)); +/// let i2p_s = I2pStream::connect(("example.i2p", port)); +/// let i2p_s = I2pStream::connect("example.i2p:12345"); +/// // I2pListener::bind(), I2pDatagramSocket::bind() and I2pDatagramSocket::send_to() behave similarly +/// let i2p_l = I2pListener::bind(); +/// let mut i2p_dg_s = I2pDatagramSocket::bind(("127.0.0.1", port)).unwrap(); +/// i2p_dg_s.send_to(&[7], (dest, 23451)).unwrap(); +/// } /// ``` pub trait ToI2pSocketAddrs { /// Returned iterator over socket addresses which this type may correspond diff --git a/src/net/datagram.rs b/src/net/datagram.rs index 5537cb4..447f40f 100644 --- a/src/net/datagram.rs +++ b/src/net/datagram.rs @@ -15,23 +15,21 @@ use std::net::{SocketAddr, ToSocketAddrs}; /// /// ```no_run /// use i2p::net::I2pDatagramSocket; -/// use i2p::Error; -/// -/// # fn foo() -> Result<()> { -/// { -/// let mut socket = I2pDatagramSocket::bind("127.0.0.1:34254")?; -/// -/// // read from the socket -/// let mut buf = [0; 10]; -/// let (amt, src) = socket.recv_from(&mut buf)?; -/// -/// // send a reply to the socket we received data from -/// let buf = &mut buf[..amt]; -/// buf.reverse(); -/// socket.send_to(buf, &src)?; -/// # Ok(()) -/// } // the socket is closed here -/// # } +/// use i2p::error::I2PError; +/// use anyhow::Result; +/// fn foo() -> Result<()> { +/// { +/// let mut socket = I2pDatagramSocket::bind("127.0.0.1:34254")?; +/// // read from the socket +/// let mut buf = [0; 10]; +/// let (amt, src) = socket.recv_from(&mut buf)?; +/// // send a reply to the socket we received data from +/// let buf = &mut buf[..amt]; +/// buf.reverse(); +/// socket.send_to(buf, &src)?; +/// } +/// // the socket is closed here +/// } /// ``` pub struct I2pDatagramSocket {}