Skip to content

Commit

Permalink
Merge protobuf errors into ConversionError
Browse files Browse the repository at this point in the history
  • Loading branch information
pronebird committed Jan 17, 2025
1 parent f8e128e commit 3730d8c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 61 deletions.
18 changes: 17 additions & 1 deletion nym-vpn-core/crates/nym-vpn-proto/src/conversions/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
// Copyright 2024 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only

use std::net::AddrParseError;

use prost::DecodeError;

#[derive(Debug, thiserror::Error)]
pub enum ConversionError {
#[error("generic error: {0}")]
#[error("Generic error: {0}")]
Generic(String),

#[error("No value set for {0}")]
NoValueSet(&'static str),

#[error("Failed to decode {0}: {1}")]
Decode(&'static str, #[source] DecodeError),

#[error("Failed to convert time {0}: {1}")]
ConvertTime(&'static str, #[source] time::Error),

#[error("Failed to parse address {0}: {1}")]
ParseAddr(&'static str, #[source] AddrParseError),
}

impl ConversionError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
// SPDX-License-Identifier: GPL-3.0-only

use std::{
net::{AddrParseError, Ipv4Addr, Ipv6Addr, SocketAddr},
net::{Ipv4Addr, Ipv6Addr, SocketAddr},
str::FromStr,
};

use nym_vpn_lib_types::{
ActionAfterDisconnect, ConnectionData, ErrorStateReason, MixnetConnectionData,
TunnelConnectionData, TunnelState, WireguardConnectionData, WireguardNode,
};
use prost::DecodeError;

use crate::{
conversions::ConversionError,
tunnel_connection_data::{
Mixnet as ProtoMixnetConnectionDataVariant, State as ProtoTunnelConnectionDataState,
Wireguard as ProtoWireguardConnectionDataVariant,
Expand Down Expand Up @@ -58,20 +58,18 @@ impl From<ProtoErrorStateReason> for ErrorStateReason {
}

impl TryFrom<ProtoTunnelState> for TunnelState {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoTunnelState) -> Result<TunnelState> {
let state = value
.state
.ok_or(FromProtobufTypeError::NoValueSet("TunnelState.state"))?;
.ok_or(ConversionError::NoValueSet("TunnelState.state"))?;

Ok(match state {
ProtoState::Disconnected(ProtoDisconnected {}) => Self::Disconnected,
ProtoState::Disconnecting(ProtoDisconnecting { after_disconnect }) => {
let proto_after_disconnect = ProtoActionAfterDisconnect::try_from(after_disconnect)
.map_err(|e| {
FromProtobufTypeError::Decode("TunnelState.after_disconnect", e)
})?;
.map_err(|e| ConversionError::Decode("TunnelState.after_disconnect", e))?;

Self::Disconnecting {
after_disconnect: ActionAfterDisconnect::from(proto_after_disconnect),
Expand All @@ -84,16 +82,14 @@ impl TryFrom<ProtoTunnelState> for TunnelState {
}
ProtoState::Connected(ProtoConnected { connection_data }) => {
let connection_data = connection_data
.ok_or(FromProtobufTypeError::NoValueSet(
"TunnelState.connection_data",
))
.ok_or(ConversionError::NoValueSet("TunnelState.connection_data"))
.and_then(ConnectionData::try_from)?;

Self::Connected { connection_data }
}
ProtoState::Error(ProtoError { reason }) => {
let reason = ProtoErrorStateReason::try_from(reason)
.map_err(|e| FromProtobufTypeError::Decode("TunnelState.after_disconnect", e))
.map_err(|e| ConversionError::Decode("TunnelState.after_disconnect", e))
.map(ErrorStateReason::from)?;
Self::Error(reason)
}
Expand All @@ -103,7 +99,7 @@ impl TryFrom<ProtoTunnelState> for TunnelState {
}

impl TryFrom<ProtoConnectionData> for ConnectionData {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoConnectionData) -> Result<Self> {
let connected_at = value
Expand All @@ -112,123 +108,106 @@ impl TryFrom<ProtoConnectionData> for ConnectionData {
crate::conversions::prost::prost_timestamp_into_offset_datetime(timestamp)
})
.transpose()
.map_err(|e| FromProtobufTypeError::ConvertTime("ConnectionData.connected_at", e))?;
.map_err(|e| ConversionError::ConvertTime("ConnectionData.connected_at", e))?;

let tunnel_connection_data = value
.tunnel
.ok_or(FromProtobufTypeError::NoValueSet("ConnectionData.tunnel"))?;
.ok_or(ConversionError::NoValueSet("ConnectionData.tunnel"))?;

Ok(Self {
connected_at,
entry_gateway: value
.entry_gateway
.ok_or(FromProtobufTypeError::NoValueSet(
"ConnectionData.entry_gateway",
))?
.ok_or(ConversionError::NoValueSet("ConnectionData.entry_gateway"))?
.id,
exit_gateway: value
.exit_gateway
.ok_or(FromProtobufTypeError::NoValueSet(
"ConnectionData.exit_gateway",
))?
.ok_or(ConversionError::NoValueSet("ConnectionData.exit_gateway"))?
.id,
tunnel: TunnelConnectionData::try_from(tunnel_connection_data)?,
})
}
}

impl TryFrom<ProtoTunnelConnectionData> for TunnelConnectionData {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoTunnelConnectionData) -> Result<Self> {
let state = value.state.ok_or(FromProtobufTypeError::NoValueSet(
"TunnelConnectionData.state",
))?;
let state = value
.state
.ok_or(ConversionError::NoValueSet("TunnelConnectionData.state"))?;

Ok(match state {
ProtoTunnelConnectionDataState::Mixnet(ProtoMixnetConnectionDataVariant { data }) => {
Self::Mixnet(MixnetConnectionData::try_from(data.ok_or(
FromProtobufTypeError::NoValueSet("TunnelConnectionData::Mixnet.data"),
ConversionError::NoValueSet("TunnelConnectionData::Mixnet.data"),
)?)?)
}
ProtoTunnelConnectionDataState::Wireguard(ProtoWireguardConnectionDataVariant {
data,
}) => Self::Wireguard(WireguardConnectionData::try_from(data.ok_or(
FromProtobufTypeError::NoValueSet("TunnelConnectionData::Wireguard.data"),
ConversionError::NoValueSet("TunnelConnectionData::Wireguard.data"),
)?)?),
})
}
}

impl TryFrom<ProtoMixnetConnectionData> for MixnetConnectionData {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoMixnetConnectionData) -> Result<Self> {
Ok(Self {
nym_address: value
.nym_address
.ok_or(FromProtobufTypeError::NoValueSet(
.ok_or(ConversionError::NoValueSet(
"MixnetConnectionData.nym_address",
))?
.nym_address,
exit_ipr: value
.exit_ipr
.ok_or(FromProtobufTypeError::NoValueSet(
"MixnetConnectionData.exit_ipr",
))?
.ok_or(ConversionError::NoValueSet("MixnetConnectionData.exit_ipr"))?
.nym_address,
ipv4: Ipv4Addr::from_str(&value.ipv4)
.map_err(|e| FromProtobufTypeError::ParseAddr("MixnetConnectionData.ipv4", e))?,
.map_err(|e| ConversionError::ParseAddr("MixnetConnectionData.ipv4", e))?,
ipv6: Ipv6Addr::from_str(&value.ipv6)
.map_err(|e| FromProtobufTypeError::ParseAddr("MixnetConnectionData.ipv6", e))?,
.map_err(|e| ConversionError::ParseAddr("MixnetConnectionData.ipv6", e))?,
})
}
}

impl TryFrom<ProtoWireguardConnectionData> for WireguardConnectionData {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoWireguardConnectionData) -> Result<Self> {
Ok(Self {
entry: WireguardNode::try_from(value.entry.ok_or(
FromProtobufTypeError::NoValueSet("WireguardConnectionData.entry"),
)?)?,
exit: WireguardNode::try_from(value.exit.ok_or(FromProtobufTypeError::NoValueSet(
"WireguardConnectionData.exit",
))?)?,
entry: WireguardNode::try_from(
value
.entry
.ok_or(ConversionError::NoValueSet("WireguardConnectionData.entry"))?,
)?,
exit: WireguardNode::try_from(
value
.exit
.ok_or(ConversionError::NoValueSet("WireguardConnectionData.exit"))?,
)?,
})
}
}

impl TryFrom<ProtoWireguardNode> for WireguardNode {
type Error = FromProtobufTypeError;
type Error = ConversionError;

fn try_from(value: ProtoWireguardNode) -> Result<Self> {
Ok(Self {
endpoint: SocketAddr::from_str(&value.endpoint)
.map_err(|e| FromProtobufTypeError::ParseAddr("WireguardNode.endpoint", e))?,
.map_err(|e| ConversionError::ParseAddr("WireguardNode.endpoint", e))?,
public_key: value.public_key,
private_ipv4: Ipv4Addr::from_str(&value.private_ipv4)
.map_err(|e| FromProtobufTypeError::ParseAddr("WireguardNode.private_ipv4", e))?,
.map_err(|e| ConversionError::ParseAddr("WireguardNode.private_ipv4", e))?,
private_ipv6: Ipv6Addr::from_str(&value.private_ipv6)
.map_err(|e| FromProtobufTypeError::ParseAddr("WireguardNode.private_ipv6", e))?,
.map_err(|e| ConversionError::ParseAddr("WireguardNode.private_ipv6", e))?,
})
}
}

#[derive(thiserror::Error, Debug)]
pub enum FromProtobufTypeError {
#[error("No value set for {0}")]
NoValueSet(&'static str),

#[error("Failed to decode {0}: {1}")]
Decode(&'static str, #[source] DecodeError),

#[error("Failed to convert time {0}: {1}")]
ConvertTime(&'static str, #[source] time::Error),

#[error("Failed to parse address {0}: {1}")]
ParseAddr(&'static str, #[source] AddrParseError),
}

pub type Result<T, E = FromProtobufTypeError> = std::result::Result<T, E>;
pub type Result<T, E = ConversionError> = std::result::Result<T, E>;

0 comments on commit 3730d8c

Please sign in to comment.