Simple functions to send and receive relay cells.
This commit is contained in:
parent
3e342a69ae
commit
d1039dda9b
5
TODO
5
TODO
|
@ -10,16 +10,17 @@ MILESTONE 0: Build a circuit and use it -- minimum to share inside tor
|
||||||
o Pick random relays
|
o Pick random relays
|
||||||
o Construct a one-hop circuit with CREATE_FAST
|
o Construct a one-hop circuit with CREATE_FAST
|
||||||
o Construct a one-hop circuit with ntor
|
o Construct a one-hop circuit with ntor
|
||||||
- Build relay cells
|
o Build relay cells
|
||||||
- Construct a multihop circuit.
|
- Construct a multihop circuit.
|
||||||
- Open a stream
|
- Open a stream
|
||||||
- Make a request, get a response (no sendmes yet)
|
- Make a request, get a response (no sendmes yet)
|
||||||
|
|
||||||
MILESTONE 1: Refactoring on above -- minimum to share outside tor
|
MILESTONE 1: Refactoring on above -- minimum to share outside tor
|
||||||
- Stop parameterizing all APIs on TLS type.
|
- Stop parameterizing all APIs on TLS type.
|
||||||
|
- Less copying, esp around Box<RawCellBody>. Consider bytes crate.
|
||||||
- Is this "reactor" business a sensible design? Is there a better one?
|
- Is this "reactor" business a sensible design? Is there a better one?
|
||||||
- Combine "create circuit" and "first hop"?
|
- Combine "create circuit" and "first hop"?
|
||||||
- Improve testing,
|
- Improve testing
|
||||||
- Improve documentation
|
- Improve documentation
|
||||||
- More types of circent for clarity.
|
- More types of circent for clarity.
|
||||||
- Make sure readme is right
|
- Make sure readme is right
|
||||||
|
|
|
@ -357,8 +357,22 @@ impl Readable for Created2 {
|
||||||
/// XXXX.
|
/// XXXX.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Relay {
|
pub struct Relay {
|
||||||
|
// XXXX either this shouldn't be boxed, or RelayCellBody should be boxed!
|
||||||
body: Box<RawCellBody>,
|
body: Box<RawCellBody>,
|
||||||
}
|
}
|
||||||
|
impl Relay {
|
||||||
|
/// Construct a Relay message from its body.
|
||||||
|
pub fn from_raw(body: RawCellBody) -> Self {
|
||||||
|
Relay {
|
||||||
|
body: Box::new(body),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Consume this Relay message and return a RelayCellBody for
|
||||||
|
/// encryption/decryption.
|
||||||
|
pub fn into_relay_cell(self) -> crate::crypto::cell::RelayCellBody {
|
||||||
|
(*self.body).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Debug for Relay {
|
impl std::fmt::Debug for Relay {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Relay").finish()
|
f.debug_struct("Relay").finish()
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
//! Multi-hop paths over the Tor network.
|
//! Multi-hop paths over the Tor network.
|
||||||
|
|
||||||
use crate::chancell::{
|
use crate::chancell::{
|
||||||
|
self,
|
||||||
msg::{self, ChanMsg},
|
msg::{self, ChanMsg},
|
||||||
ChanCell, CircID,
|
ChanCell, CircID,
|
||||||
};
|
};
|
||||||
use crate::channel::Channel;
|
use crate::channel::Channel;
|
||||||
use crate::crypto::cell::{ClientLayer, CryptInit};
|
use crate::crypto::cell::{ClientLayer, CryptInit};
|
||||||
use crate::crypto::handshake::{ClientHandshake, KeyGenerator};
|
use crate::crypto::handshake::{ClientHandshake, KeyGenerator};
|
||||||
|
use crate::relaycell::msg::RelayCell;
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use futures::io::{AsyncRead, AsyncWrite};
|
use futures::io::{AsyncRead, AsyncWrite};
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{thread_rng, CryptoRng, Rng};
|
||||||
|
|
||||||
use crate::crypto::cell::ClientCrypt;
|
use crate::crypto::cell::ClientCrypt;
|
||||||
|
|
||||||
|
@ -65,6 +67,53 @@ where
|
||||||
self.input.next().await.ok_or(Error::CircuitClosed)
|
self.input.next().await.ok_or(Error::CircuitClosed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encode the message `msg`, encrypt it, and send it to the 'hop'th hop.
|
||||||
|
///
|
||||||
|
/// TODO: This is not a good long-term API. It should become private
|
||||||
|
/// if we keep it.
|
||||||
|
///
|
||||||
|
/// TODO: use HopNum
|
||||||
|
pub async fn send_relay_cell(&mut self, hop: u8, early: bool, cell: RelayCell) -> Result<()> {
|
||||||
|
assert!((hop as usize) < self.crypto.n_layers());
|
||||||
|
let mut body = cell.encode(&mut thread_rng())?;
|
||||||
|
self.crypto.encrypt(&mut body, hop)?;
|
||||||
|
let msg = chancell::msg::Relay::from_raw(body.into());
|
||||||
|
let msg = if early {
|
||||||
|
ChanMsg::RelayEarly(msg)
|
||||||
|
} else {
|
||||||
|
ChanMsg::Relay(msg)
|
||||||
|
};
|
||||||
|
self.send_msg(msg).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Receive a message from the circuit, decrypt it, and return it as a
|
||||||
|
/// RelayCell.
|
||||||
|
///
|
||||||
|
/// TODO: This is not a good long-term API. It should become private
|
||||||
|
/// if we keep it.
|
||||||
|
///
|
||||||
|
/// TODO: use HopNum
|
||||||
|
pub async fn recv_relay_cell(&mut self) -> Result<(u8, RelayCell)> {
|
||||||
|
let chanmsg = self.read_msg().await?;
|
||||||
|
let body = match chanmsg {
|
||||||
|
ChanMsg::Relay(r) => r,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::ChanProto(format!(
|
||||||
|
"{} cell received on circuit",
|
||||||
|
chanmsg.get_cmd()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Decrypt, if possible.
|
||||||
|
let mut cell = body.into_relay_cell();
|
||||||
|
let hopnum = self.crypto.decrypt(&mut cell)?;
|
||||||
|
let msg = RelayCell::decode(cell)?;
|
||||||
|
|
||||||
|
Ok((hopnum, msg))
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper: create the first hop of a circuit.
|
/// Helper: create the first hop of a circuit.
|
||||||
///
|
///
|
||||||
/// This is parameterized not just on the RNG, but a wrapper object to
|
/// This is parameterized not just on the RNG, but a wrapper object to
|
||||||
|
|
|
@ -124,6 +124,8 @@ impl ClientCrypt {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of layers configured on this ClientCrypt.
|
/// Return the number of layers configured on this ClientCrypt.
|
||||||
|
///
|
||||||
|
/// TODO: use HopNum
|
||||||
pub fn n_layers(&self) -> usize {
|
pub fn n_layers(&self) -> usize {
|
||||||
self.layers.len()
|
self.layers.len()
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,14 @@ impl RelayCell {
|
||||||
///
|
///
|
||||||
/// Requires that the cryptographic checks on the message have already been
|
/// Requires that the cryptographic checks on the message have already been
|
||||||
/// performed
|
/// performed
|
||||||
|
pub fn decode(body: RelayCellBody) -> Result<Self> {
|
||||||
|
let mut reader = Reader::from_slice(body.as_ref());
|
||||||
|
RelayCell::decode_from_reader(&mut reader)
|
||||||
|
}
|
||||||
|
/// Parse a RELAY or RELAY_EARLY cell body into a RelayCell from a reader.
|
||||||
|
///
|
||||||
|
/// Requires that the cryptographic checks on the message have already been
|
||||||
|
/// performed
|
||||||
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
let cmd = r.take_u8()?.into();
|
let cmd = r.take_u8()?.into();
|
||||||
r.advance(2)?; // "recognized"
|
r.advance(2)?; // "recognized"
|
||||||
|
|
Loading…
Reference in New Issue