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 Construct a one-hop circuit with CREATE_FAST
|
||||
o Construct a one-hop circuit with ntor
|
||||
- Build relay cells
|
||||
o Build relay cells
|
||||
- Construct a multihop circuit.
|
||||
- Open a stream
|
||||
- Make a request, get a response (no sendmes yet)
|
||||
|
||||
MILESTONE 1: Refactoring on above -- minimum to share outside tor
|
||||
- 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?
|
||||
- Combine "create circuit" and "first hop"?
|
||||
- Improve testing,
|
||||
- Improve testing
|
||||
- Improve documentation
|
||||
- More types of circent for clarity.
|
||||
- Make sure readme is right
|
||||
|
|
|
@ -357,8 +357,22 @@ impl Readable for Created2 {
|
|||
/// XXXX.
|
||||
#[derive(Clone)]
|
||||
pub struct Relay {
|
||||
// XXXX either this shouldn't be boxed, or RelayCellBody should be boxed!
|
||||
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 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Relay").finish()
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
//! Multi-hop paths over the Tor network.
|
||||
|
||||
use crate::chancell::{
|
||||
self,
|
||||
msg::{self, ChanMsg},
|
||||
ChanCell, CircID,
|
||||
};
|
||||
use crate::channel::Channel;
|
||||
use crate::crypto::cell::{ClientLayer, CryptInit};
|
||||
use crate::crypto::handshake::{ClientHandshake, KeyGenerator};
|
||||
use crate::relaycell::msg::RelayCell;
|
||||
use crate::{Error, Result};
|
||||
|
||||
use futures::channel::mpsc;
|
||||
use futures::io::{AsyncRead, AsyncWrite};
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
use rand::{CryptoRng, Rng};
|
||||
use rand::{thread_rng, CryptoRng, Rng};
|
||||
|
||||
use crate::crypto::cell::ClientCrypt;
|
||||
|
||||
|
@ -65,6 +67,53 @@ where
|
|||
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.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// TODO: use HopNum
|
||||
pub fn n_layers(&self) -> usize {
|
||||
self.layers.len()
|
||||
}
|
||||
|
|
|
@ -73,6 +73,14 @@ impl RelayCell {
|
|||
///
|
||||
/// Requires that the cryptographic checks on the message have already been
|
||||
/// 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> {
|
||||
let cmd = r.take_u8()?.into();
|
||||
r.advance(2)?; // "recognized"
|
||||
|
|
Loading…
Reference in New Issue