net: fix network address parsing

This commit is contained in:
Boog900 2024-01-30 17:53:03 +00:00
parent 83b59c557c
commit ec4fe9b79d
No known key found for this signature in database
GPG key ID: 5401367FB7302004
9 changed files with 58 additions and 29 deletions

View file

@ -33,7 +33,9 @@ impl<T: Containerable + EpeeValue> EpeeValue for ContainerAsBlob<T> {
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> { fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
let bytes = Bytes::read(r, marker)?; let bytes = Bytes::read(r, marker)?;
if bytes.len() % T::SIZE != 0 { if bytes.len() % T::SIZE != 0 {
return Err(Error::Value("Can't convert blob container to Vec type.")); return Err(Error::Value(
"Can't convert blob container to Vec type.".to_string(),
));
} }
Ok(ContainerAsBlob( Ok(ContainerAsBlob(

View file

@ -10,7 +10,7 @@ pub enum Error {
#[cfg_attr(feature = "std", error("Format error: {0}"))] #[cfg_attr(feature = "std", error("Format error: {0}"))]
Format(&'static str), Format(&'static str),
#[cfg_attr(feature = "std", error("Value error: {0}"))] #[cfg_attr(feature = "std", error("Value error: {0}"))]
Value(&'static str), Value(String),
} }
impl Error { impl Error {
@ -22,7 +22,7 @@ impl Error {
} }
} }
fn field_data(&self) -> &'static str { fn field_data(&self) -> &str {
match self { match self {
Error::IO(data) => data, Error::IO(data) => data,
Error::Format(data) => data, Error::Format(data) => data,
@ -41,12 +41,12 @@ impl Debug for Error {
impl From<TryFromIntError> for Error { impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Self { fn from(_: TryFromIntError) -> Self {
Error::Value("Int is too large") Error::Value("Int is too large".to_string())
} }
} }
impl From<Utf8Error> for Error { impl From<Utf8Error> for Error {
fn from(_: Utf8Error) -> Self { fn from(_: Utf8Error) -> Self {
Error::Value("Invalid utf8 str") Error::Value("Invalid utf8 str".to_string())
} }
} }

View file

@ -51,7 +51,7 @@
//! //!
//! //!
//! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode; //! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
//! let val: Test = from_bytes(&mut &data).unwrap(); //! let val: Test = from_bytes(&mut data.as_slice()).unwrap();
//! let data = to_bytes(val).unwrap(); //! let data = to_bytes(val).unwrap();
//! //!
//! //!
@ -79,7 +79,7 @@
//! //!
//! //!
//! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode; //! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
//! let val: Test2 = from_bytes(&mut &data).unwrap(); //! let val: Test2 = from_bytes(&mut data.as_slice()).unwrap();
//! let data = to_bytes(val).unwrap(); //! let data = to_bytes(val).unwrap();
//! //!
//! ``` //! ```
@ -279,7 +279,7 @@ fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
if let Some(size) = marker.inner_marker.size() { if let Some(size) = marker.inner_marker.size() {
let bytes_to_skip = size let bytes_to_skip = size
.checked_mul(len.try_into()?) .checked_mul(len.try_into()?)
.ok_or(Error::Value("List is too big"))?; .ok_or(Error::Value("List is too big".to_string()))?;
return advance(bytes_to_skip, r); return advance(bytes_to_skip, r);
}; };

View file

@ -57,7 +57,7 @@ macro_rules! epee_object {
if core::mem::replace(&mut self.$field, Some( if core::mem::replace(&mut self.$field, Some(
epee_encoding::try_right_then_left!(epee_encoding::read_epee_value(b)?, $($read_fn(b)?)?) epee_encoding::try_right_then_left!(epee_encoding::read_epee_value(b)?, $($read_fn(b)?)?)
)).is_some() { )).is_some() {
Err(epee_encoding::error::Error::Value("Duplicate field in data"))?; Err(epee_encoding::error::Error::Value(format!("Duplicate field in data: {}", epee_encoding::field_name!($field, $($alt_name)?))))?;
} }
Ok(true) Ok(true)
},)+ },)+
@ -87,7 +87,7 @@ macro_rules! epee_object {
$(.or(Some($default)))? $(.or(Some($default)))?
.or(epee_default_value) .or(epee_default_value)
$(.map(<$ty_as>::into))? $(.map(<$ty_as>::into))?
.ok_or(epee_encoding::error::Error::Value("Missing field in data"))? .ok_or(epee_encoding::error::Error::Value(format!("Missing field in data: {}", epee_encoding::field_name!($field, $($alt_name)?))))?
}, },
)+ )+

View file

@ -189,6 +189,14 @@ impl EpeeValue for Vec<u8> {
Ok(res) Ok(res)
} }
fn epee_default_value() -> Option<Self> {
Some(Vec::new())
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> { fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?; write_varint(self.len().try_into()?, w)?;
@ -222,6 +230,14 @@ impl EpeeValue for Bytes {
Ok(r.copy_to_bytes(len.try_into()?)) Ok(r.copy_to_bytes(len.try_into()?))
} }
fn epee_default_value() -> Option<Self> {
Some(Bytes::new())
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> { fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?; write_varint(self.len().try_into()?, w)?;
@ -258,6 +274,14 @@ impl EpeeValue for BytesMut {
Ok(bytes) Ok(bytes)
} }
fn epee_default_value() -> Option<Self> {
Some(BytesMut::new())
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> { fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?; write_varint(self.len().try_into()?, w)?;
@ -287,7 +311,7 @@ impl<const N: usize> EpeeValue for ByteArrayVec<N> {
if r.remaining() if r.remaining()
< usize::try_from(len)? < usize::try_from(len)?
.checked_mul(N) .checked_mul(N)
.ok_or(Error::Value("Length of field is too long"))? .ok_or(Error::Value("Length of field is too long".to_string()))?
{ {
return Err(Error::IO("Not enough bytes to fill object")); return Err(Error::IO("Not enough bytes to fill object"));
} }
@ -296,6 +320,14 @@ impl<const N: usize> EpeeValue for ByteArrayVec<N> {
.map_err(|_| Error::Format("Field has invalid length")) .map_err(|_| Error::Format("Field has invalid length"))
} }
fn epee_default_value() -> Option<Self> {
Some(ByteArrayVec::try_from(Bytes::new()).unwrap())
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> { fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
let bytes = self.take_bytes(); let bytes = self.take_bytes();

View file

@ -18,7 +18,7 @@
//! I2p. Currently this module only has IPv(4/6). //! I2p. Currently this module only has IPv(4/6).
//! //!
use bytes::BufMut; use bytes::BufMut;
use epee_encoding::{EpeeObject, EpeeValue}; use epee_encoding::EpeeObject;
use std::{hash::Hash, net, net::SocketAddr}; use std::{hash::Hash, net, net::SocketAddr};
mod serde_helper; mod serde_helper;
@ -46,7 +46,7 @@ impl EpeeObject for NetworkAddress {
} }
fn write_fields<B: BufMut>(self, w: &mut B) -> epee_encoding::Result<()> { fn write_fields<B: BufMut>(self, w: &mut B) -> epee_encoding::Result<()> {
TaggedNetworkAddress::from(self).write(w) TaggedNetworkAddress::from(self).write_fields(w)
} }
} }

View file

@ -14,7 +14,7 @@ pub struct TaggedNetworkAddress {
epee_object!( epee_object!(
TaggedNetworkAddress, TaggedNetworkAddress,
ty: Option<u8>, ty("type"): Option<u8>,
addr: Option<AllFieldsNetworkAddress>, addr: Option<AllFieldsNetworkAddress>,
); );
@ -27,21 +27,21 @@ impl EpeeObjectBuilder<NetworkAddress> for TaggedNetworkAddress {
{ {
return Err(epee_encoding::Error::Format("Duplicate field in data.")); return Err(epee_encoding::Error::Format("Duplicate field in data."));
} }
Ok(true)
} }
"addr" => { "addr" => {
if std::mem::replace(&mut self.addr, epee_encoding::read_epee_value(b)?).is_some() { if std::mem::replace(&mut self.addr, epee_encoding::read_epee_value(b)?).is_some() {
return Err(epee_encoding::Error::Format("Duplicate field in data.")); return Err(epee_encoding::Error::Format("Duplicate field in data."));
} }
Ok(true)
} }
_ => return Ok(false), _ => Ok(false),
} }
Ok(true)
} }
fn finish(self) -> epee_encoding::Result<NetworkAddress> { fn finish(self) -> epee_encoding::Result<NetworkAddress> {
self.try_into() self.try_into()
.map_err(|_| epee_encoding::Error::Value("Invalid network address")) .map_err(|_| epee_encoding::Error::Value("Invalid network address".to_string()))
} }
} }
@ -70,7 +70,7 @@ impl From<NetworkAddress> for TaggedNetworkAddress {
addr: Some(AllFieldsNetworkAddress { addr: Some(AllFieldsNetworkAddress {
m_ip: Some(u32::from_be_bytes(addr.ip().octets())), m_ip: Some(u32::from_be_bytes(addr.ip().octets())),
m_port: Some(addr.port()), m_port: Some(addr.port()),
..Default::default() addr: None,
}), }),
}, },
SocketAddr::V6(addr) => TaggedNetworkAddress { SocketAddr::V6(addr) => TaggedNetworkAddress {
@ -78,7 +78,7 @@ impl From<NetworkAddress> for TaggedNetworkAddress {
addr: Some(AllFieldsNetworkAddress { addr: Some(AllFieldsNetworkAddress {
addr: Some(addr.ip().octets()), addr: Some(addr.ip().octets()),
m_port: Some(addr.port()), m_port: Some(addr.port()),
..Default::default() m_ip: None,
}), }),
}, },
}, },

View file

@ -115,7 +115,6 @@ epee_object!(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{BasicNodeData, CoreSyncData, HandshakeRequest, HandshakeResponse}; use super::{BasicNodeData, CoreSyncData, HandshakeRequest, HandshakeResponse};
use crate::p2p::common::PeerSupportFlags; use crate::p2p::common::PeerSupportFlags;
@ -971,6 +970,7 @@ mod tests {
assert_eq!(250, handshake.local_peerlist_new.len()); assert_eq!(250, handshake.local_peerlist_new.len());
let mut encoded_bytes = epee_encoding::to_bytes(handshake.clone()).unwrap(); let mut encoded_bytes = epee_encoding::to_bytes(handshake.clone()).unwrap();
let handshake_2: HandshakeResponse = epee_encoding::from_bytes(&mut encoded_bytes).unwrap(); let handshake_2: HandshakeResponse = epee_encoding::from_bytes(&mut encoded_bytes).unwrap();
assert_eq!(handshake, handshake_2); assert_eq!(handshake, handshake_2);

View file

@ -171,13 +171,6 @@ epee_object! {
rpc_credits_per_hash: u32 = 0_u32, rpc_credits_per_hash: u32 = 0_u32,
} }
impl std::hash::Hash for PeerListEntryBase {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// We only hash the adr so we can look this up in a HashSet.
self.adr.hash(state)
}
}
/// A pruned tx with the hash of the missing prunable data /// A pruned tx with the hash of the missing prunable data
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct PrunedTxBlobEntry { pub struct PrunedTxBlobEntry {
@ -256,7 +249,9 @@ fn tx_blob_read<B: Buf>(b: &mut B) -> epee_encoding::Result<TransactionBlobs> {
match marker.inner_marker { match marker.inner_marker {
InnerMarker::Object => Ok(TransactionBlobs::Pruned(Vec::read(b, &marker)?)), InnerMarker::Object => Ok(TransactionBlobs::Pruned(Vec::read(b, &marker)?)),
InnerMarker::String => Ok(TransactionBlobs::Normal(Vec::read(b, &marker)?)), InnerMarker::String => Ok(TransactionBlobs::Normal(Vec::read(b, &marker)?)),
_ => Err(epee_encoding::Error::Value("Invalid marker for tx blobs")), _ => Err(epee_encoding::Error::Value(
"Invalid marker for tx blobs".to_string(),
)),
} }
} }