Turn End reasons into a caret enumeration.

This commit is contained in:
Nick Mathewson 2020-10-19 13:31:46 -04:00
parent f2ebc94088
commit e83d8ec3c2
2 changed files with 48 additions and 16 deletions

View File

@ -6,6 +6,7 @@
use super::RelayCmd;
use crate::chancell::msg::{TAP_C_HANDSHAKE_LEN, TAP_S_HANDSHAKE_LEN};
use crate::chancell::CELL_DATA_LEN;
use caret::caret_int;
use std::net::{IpAddr, Ipv4Addr};
use tor_bytes::{Error, Result};
use tor_bytes::{Readable, Reader, Writeable, Writer};
@ -263,38 +264,69 @@ impl Body for Data {
#[derive(Debug, Clone)]
pub struct End {
/// Reason for closing the stream
reason: u8,
reason: EndReason,
/// If the reason is EXITPOLICY, this holds the resolved address an
/// associated TTL.
addr: Option<(IpAddr, u32)>,
}
/// Closing a stream because of an unspecified reason.
///
/// This is the only END reason that clients send.
const REASON_MISC: u8 = 1;
/// Closing a stream because of an exit-policy violation.
const REASON_EXITPOLICY: u8 = 4;
caret_int! {
/// A delcared reason for closing a stream
pub struct EndReason(u8) {
/// Closing a stream because of an unspecified reason.
///
/// This is the only END reason that clients send.
MISC = 1,
/// Couldn't look up hostname.
RESOLVEFAILED = 2,
/// Remote host refused connection *
CONNECTREFUSED = 3,
/// Closing a stream because of an exit-policy violation.
EXITPOLICY = 4,
/// Circuit destroyed
DESTROY = 5,
/// TCP connection was closed
DONE = 6,
/// Connection timed out, or OR timed out while connecting
TIMEOUT = 7,
/// No route to target destination.
NOROUTE = 8,
/// OR is entering hibernation and not handling requests
HIBERNATING = 9,
/// Internal error at the OR
INTERNAL = 10,
/// Ran out of resources to fulfill requests
RESOURCELIMIT = 11,
/// Connection unexpectedly reset
CONNRESET = 12,
/// Tor protocol violation
TORPROTOCOL = 13,
/// BEGIN_DIR cell at a non-directory-cache.
NOTDIRECTORY = 14,
}
}
impl End {
/// Make a new END_REASON_MISC message.
///
/// Clients send this every time they decide to close a stream.
pub fn new_misc() -> Self {
End {
reason: REASON_MISC,
reason: EndReason::MISC,
addr: None,
}
}
/// Make a new END message with the provided end reason.
///
/// TODO: reason should be an enum-like thing. XXXXM3
pub fn new_with_reason(reason: u8) -> Self {
pub fn new_with_reason(reason: EndReason) -> Self {
End { reason, addr: None }
}
/// Make a new END message with END_REASON_EXITPOLICY, and the
/// provided address and ttl.
pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
End {
reason: REASON_EXITPOLICY,
reason: EndReason::EXITPOLICY,
addr: Some((addr, ttl)),
}
}
@ -307,12 +339,12 @@ impl Body for End {
if r.remaining() == 0 {
// XXXX Or is this an error? XXXXM3
return Ok(End {
reason: REASON_MISC,
reason: EndReason::MISC,
addr: None,
});
}
let reason = r.take_u8()?;
if reason == REASON_EXITPOLICY {
let reason = r.take_u8()?.into();
if reason == EndReason::EXITPOLICY {
let addr = match r.remaining() {
8 => IpAddr::V4(r.extract()?),
20 => IpAddr::V6(r.extract()?),
@ -332,8 +364,8 @@ impl Body for End {
}
}
fn encode_onto(self, w: &mut Vec<u8>) {
w.write_u8(self.reason);
if self.reason == REASON_EXITPOLICY && self.addr.is_some() {
w.write_u8(self.reason.into());
if self.reason == EndReason::EXITPOLICY && self.addr.is_some() {
let (addr, ttl) = self.addr.unwrap();
match addr {
IpAddr::V4(v4) => w.write(&v4),

View File

@ -104,7 +104,7 @@ fn test_end() {
assert_eq!(Into::<u8>::into(cmd), 3_u8);
msg(cmd, "01", &msg::End::new_misc().into());
msg(cmd, "06", &msg::End::new_with_reason(6).into());
msg(cmd, "06", &msg::End::new_with_reason(6.into()).into());
// hand-generated, for exit policy rejections
let localhost = "127.0.0.7".parse::<IpAddr>().unwrap();