83 lines
2.7 KiB
Rust
83 lines
2.7 KiB
Rust
use addressing;
|
|
use addressing::AddressTypeError;
|
|
use sphinx::route::{Destination, DestinationAddressBytes, SURBIdentifier};
|
|
use sphinx::SphinxPacket;
|
|
use std::net::SocketAddr;
|
|
use topology::{NymTopology, NymTopologyError};
|
|
|
|
pub const LOOP_COVER_MESSAGE_PAYLOAD: &[u8] = b"The cake is a lie!";
|
|
pub const LOOP_COVER_MESSAGE_AVERAGE_DELAY: f64 = 2.0;
|
|
|
|
#[derive(Debug)]
|
|
pub enum SphinxPacketEncapsulationError {
|
|
NoValidProvidersError,
|
|
InvalidTopologyError,
|
|
SphinxEncapsulationError(sphinx::header::SphinxUnwrapError),
|
|
InvalidFirstMixAddress,
|
|
}
|
|
|
|
impl From<topology::NymTopologyError> for SphinxPacketEncapsulationError {
|
|
fn from(_: NymTopologyError) -> Self {
|
|
use SphinxPacketEncapsulationError::*;
|
|
InvalidTopologyError
|
|
}
|
|
}
|
|
|
|
// it is correct error we're converting from, it just has an unfortunate name
|
|
// related issue: https://github.com/nymtech/sphinx/issues/40
|
|
impl From<sphinx::header::SphinxUnwrapError> for SphinxPacketEncapsulationError {
|
|
fn from(err: sphinx::header::SphinxUnwrapError) -> Self {
|
|
use SphinxPacketEncapsulationError::*;
|
|
SphinxEncapsulationError(err)
|
|
}
|
|
}
|
|
|
|
impl From<AddressTypeError> for SphinxPacketEncapsulationError {
|
|
fn from(_: AddressTypeError) -> Self {
|
|
use SphinxPacketEncapsulationError::*;
|
|
InvalidFirstMixAddress
|
|
}
|
|
}
|
|
|
|
pub fn loop_cover_message<T: NymTopology>(
|
|
our_address: DestinationAddressBytes,
|
|
surb_id: SURBIdentifier,
|
|
topology: &T,
|
|
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
|
let destination = Destination::new(our_address, surb_id);
|
|
|
|
encapsulate_message(
|
|
destination,
|
|
LOOP_COVER_MESSAGE_PAYLOAD.to_vec(),
|
|
topology,
|
|
LOOP_COVER_MESSAGE_AVERAGE_DELAY,
|
|
)
|
|
}
|
|
|
|
pub fn encapsulate_message<T: NymTopology>(
|
|
recipient: Destination,
|
|
message: Vec<u8>,
|
|
topology: &T,
|
|
average_delay: f64,
|
|
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
|
let mut providers = topology.providers();
|
|
if providers.len() == 0 {
|
|
return Err(SphinxPacketEncapsulationError::NoValidProvidersError);
|
|
}
|
|
// unwrap is fine here as we asserted there is at least single provider
|
|
let provider = providers.pop().unwrap().into();
|
|
|
|
let route = topology.route_to(provider)?;
|
|
|
|
let delays = sphinx::header::delays::generate(route.len(), average_delay);
|
|
|
|
// build the packet
|
|
let packet = sphinx::SphinxPacket::new(message, &route[..], &recipient, &delays)?;
|
|
|
|
// we know the mix route must be valid otherwise we would have already returned an error
|
|
let first_node_address =
|
|
addressing::socket_address_from_encoded_bytes(route.first().unwrap().address.to_bytes())?;
|
|
|
|
Ok((first_node_address, packet))
|
|
}
|