tor-cell: Use macro to define RelayMsg type too.
This commit is contained in:
parent
f5f8402d50
commit
706a39a870
|
@ -18,84 +18,89 @@ use tor_llcrypto::pk::rsa::RsaIdentity;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
use super::onion_service;
|
pub use super::onion_service::{
|
||||||
|
EstablishIntro, EstablishRendezvous, IntroEstablished, Introduce1, Introduce2, IntroduceAck,
|
||||||
|
Rendezvous1, Rendezvous2, RendezvousEstablished,
|
||||||
|
};
|
||||||
#[cfg(feature = "experimental-udp")]
|
#[cfg(feature = "experimental-udp")]
|
||||||
use super::udp;
|
pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
|
||||||
|
|
||||||
|
crate::restrict::restricted_msg! {
|
||||||
/// A single parsed relay message, sent or received along a circuit
|
/// A single parsed relay message, sent or received along a circuit
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum RelayMsg {
|
pub enum RelayMsg : RelayMsg {
|
||||||
/// Create a stream
|
/// Create a stream
|
||||||
Begin(Begin),
|
Begin,
|
||||||
/// Send data on a stream
|
/// Send data on a stream
|
||||||
Data(Data),
|
Data,
|
||||||
/// Close a stream
|
/// Close a stream
|
||||||
End(End),
|
End,
|
||||||
/// Successful response to a Begin message
|
/// Successful response to a Begin message
|
||||||
Connected(Connected),
|
Connected,
|
||||||
/// For flow control
|
/// For flow control
|
||||||
Sendme(Sendme),
|
Sendme,
|
||||||
/// Extend a circuit to a new hop (deprecated)
|
/// Extend a circuit to a new hop (deprecated)
|
||||||
Extend(Extend),
|
Extend,
|
||||||
/// Successful response to an Extend message (deprecated)
|
/// Successful response to an Extend message (deprecated)
|
||||||
Extended(Extended),
|
Extended,
|
||||||
/// Extend a circuit to a new hop
|
/// Extend a circuit to a new hop
|
||||||
Extend2(Extend2),
|
Extend2,
|
||||||
/// Successful response to an Extend2 message
|
/// Successful response to an Extend2 message
|
||||||
Extended2(Extended2),
|
Extended2,
|
||||||
/// Partially close a circuit
|
/// Partially close a circuit
|
||||||
Truncate(Truncate),
|
Truncate,
|
||||||
/// Tell the client that a circuit has been partially closed
|
/// Tell the client that a circuit has been partially closed
|
||||||
Truncated(Truncated),
|
Truncated,
|
||||||
/// Used for padding
|
/// Used for padding
|
||||||
Drop(Drop),
|
Drop,
|
||||||
/// Launch a DNS request
|
/// Launch a DNS request
|
||||||
Resolve(Resolve),
|
Resolve,
|
||||||
/// Response to a Resolve message
|
/// Response to a Resolve message
|
||||||
Resolved(Resolved),
|
Resolved,
|
||||||
/// Start a directory stream
|
/// Start a directory stream
|
||||||
BeginDir(BeginDir),
|
BeginDir,
|
||||||
/// Start a UDP stream.
|
/// Start a UDP stream.
|
||||||
#[cfg(feature = "experimental-udp")]
|
#[cfg(feature = "experimental-udp")]
|
||||||
ConnectUdp(udp::ConnectUdp),
|
ConnectUdp,
|
||||||
/// Successful response to a ConnectUdp message
|
/// Successful response to a ConnectUdp message
|
||||||
#[cfg(feature = "experimental-udp")]
|
#[cfg(feature = "experimental-udp")]
|
||||||
ConnectedUdp(udp::ConnectedUdp),
|
ConnectedUdp,
|
||||||
/// UDP stream data
|
/// UDP stream data
|
||||||
#[cfg(feature = "experimental-udp")]
|
#[cfg(feature = "experimental-udp")]
|
||||||
Datagram(udp::Datagram),
|
Datagram,
|
||||||
|
|
||||||
/// Establish Introduction
|
/// Establish Introduction
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
EstablishIntro(onion_service::EstablishIntro),
|
EstablishIntro,
|
||||||
/// Establish Rendezvous
|
/// Establish Rendezvous
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
EstablishRendezvous(onion_service::EstablishRendezvous),
|
EstablishRendezvous,
|
||||||
/// Introduce1 (client to introduction point)
|
/// Introduce1 (client to introduction point)
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
Introduce1(onion_service::Introduce1),
|
Introduce1,
|
||||||
/// Introduce2 (introduction point to service)
|
/// Introduce2 (introduction point to service)
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
Introduce2(onion_service::Introduce2),
|
Introduce2,
|
||||||
/// Rendezvous1 (service to rendezvous point)
|
/// Rendezvous1 (service to rendezvous point)
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
Rendezvous1(onion_service::Rendezvous1),
|
Rendezvous1,
|
||||||
/// Rendezvous2 (rendezvous point to client)
|
/// Rendezvous2 (rendezvous point to client)
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
Rendezvous2(onion_service::Rendezvous2),
|
Rendezvous2,
|
||||||
/// Acknowledgement for EstablishIntro.
|
/// Acknowledgement for EstablishIntro.
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
IntroEstablished(onion_service::IntroEstablished),
|
IntroEstablished,
|
||||||
/// Acknowledgment for EstalishRendezvous.
|
/// Acknowledgment for EstablishRendezvous.
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
RendEstablished,
|
RendezvousEstablished,
|
||||||
/// Acknowledgement for Introduce1.
|
/// Acknowledgement for Introduce1.
|
||||||
#[cfg(feature = "onion-service")]
|
#[cfg(feature = "onion-service")]
|
||||||
IntroduceAck(onion_service::IntroduceAck),
|
IntroduceAck,
|
||||||
|
|
||||||
|
_ =>
|
||||||
/// An unrecognized command.
|
/// An unrecognized command.
|
||||||
Unrecognized(Unrecognized),
|
Unrecognized,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal: traits in common different cell bodies.
|
/// Internal: traits in common different cell bodies.
|
||||||
|
@ -114,156 +119,6 @@ impl<B: Body> From<B> for RelayMsg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::RelayMsgClass for RelayMsg {
|
|
||||||
fn cmd(&self) -> RelayCmd {
|
|
||||||
use RelayMsg::*;
|
|
||||||
match self {
|
|
||||||
Begin(_) => RelayCmd::BEGIN,
|
|
||||||
Data(_) => RelayCmd::DATA,
|
|
||||||
End(_) => RelayCmd::END,
|
|
||||||
Connected(_) => RelayCmd::CONNECTED,
|
|
||||||
Sendme(_) => RelayCmd::SENDME,
|
|
||||||
Extend(_) => RelayCmd::EXTEND,
|
|
||||||
Extended(_) => RelayCmd::EXTENDED,
|
|
||||||
Extend2(_) => RelayCmd::EXTEND2,
|
|
||||||
Extended2(_) => RelayCmd::EXTENDED2,
|
|
||||||
Truncate(_) => RelayCmd::TRUNCATE,
|
|
||||||
Truncated(_) => RelayCmd::TRUNCATED,
|
|
||||||
Drop(_) => RelayCmd::DROP,
|
|
||||||
Resolve(_) => RelayCmd::RESOLVE,
|
|
||||||
Resolved(_) => RelayCmd::RESOLVED,
|
|
||||||
BeginDir(_) => RelayCmd::BEGIN_DIR,
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
ConnectUdp(_) => RelayCmd::CONNECT_UDP,
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
ConnectedUdp(_) => RelayCmd::CONNECTED_UDP,
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
Datagram(_) => RelayCmd::DATAGRAM,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
EstablishIntro(_) => RelayCmd::ESTABLISH_INTRO,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
EstablishRendezvous(_) => RelayCmd::ESTABLISH_RENDEZVOUS,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Introduce1(_) => RelayCmd::INTRODUCE1,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Introduce2(_) => RelayCmd::INTRODUCE2,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Rendezvous1(_) => RelayCmd::RENDEZVOUS1,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Rendezvous2(_) => RelayCmd::RENDEZVOUS2,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
IntroEstablished(_) => RelayCmd::INTRO_ESTABLISHED,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
RendEstablished => RelayCmd::RENDEZVOUS_ESTABLISHED,
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
IntroduceAck(_) => RelayCmd::INTRODUCE_ACK,
|
|
||||||
|
|
||||||
Unrecognized(u) => u.cmd(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decode_from_reader(c: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
|
|
||||||
Ok(match c {
|
|
||||||
RelayCmd::BEGIN => RelayMsg::Begin(Begin::decode_from_reader(r)?),
|
|
||||||
RelayCmd::DATA => RelayMsg::Data(Data::decode_from_reader(r)?),
|
|
||||||
RelayCmd::END => RelayMsg::End(End::decode_from_reader(r)?),
|
|
||||||
RelayCmd::CONNECTED => RelayMsg::Connected(Connected::decode_from_reader(r)?),
|
|
||||||
RelayCmd::SENDME => RelayMsg::Sendme(Sendme::decode_from_reader(r)?),
|
|
||||||
RelayCmd::EXTEND => RelayMsg::Extend(Extend::decode_from_reader(r)?),
|
|
||||||
RelayCmd::EXTENDED => RelayMsg::Extended(Extended::decode_from_reader(r)?),
|
|
||||||
RelayCmd::EXTEND2 => RelayMsg::Extend2(Extend2::decode_from_reader(r)?),
|
|
||||||
RelayCmd::EXTENDED2 => RelayMsg::Extended2(Extended2::decode_from_reader(r)?),
|
|
||||||
RelayCmd::TRUNCATE => RelayMsg::Truncate(Truncate::decode_from_reader(r)?),
|
|
||||||
RelayCmd::TRUNCATED => RelayMsg::Truncated(Truncated::decode_from_reader(r)?),
|
|
||||||
RelayCmd::DROP => RelayMsg::Drop(Drop::decode_from_reader(r)?),
|
|
||||||
RelayCmd::RESOLVE => RelayMsg::Resolve(Resolve::decode_from_reader(r)?),
|
|
||||||
RelayCmd::RESOLVED => RelayMsg::Resolved(Resolved::decode_from_reader(r)?),
|
|
||||||
RelayCmd::BEGIN_DIR => RelayMsg::BeginDir(BeginDir::decode_from_reader(r)?),
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
RelayCmd::CONNECT_UDP => RelayMsg::ConnectUdp(udp::ConnectUdp::decode_from_reader(r)?),
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
RelayCmd::CONNECTED_UDP => {
|
|
||||||
RelayMsg::ConnectedUdp(udp::ConnectedUdp::decode_from_reader(r)?)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
RelayCmd::DATAGRAM => RelayMsg::Datagram(udp::Datagram::decode_from_reader(r)?),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
RelayCmd::ESTABLISH_INTRO => {
|
|
||||||
RelayMsg::EstablishIntro(onion_service::EstablishIntro::decode_from_reader(r)?)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
RelayCmd::ESTABLISH_RENDEZVOUS => RelayMsg::EstablishRendezvous(
|
|
||||||
onion_service::EstablishRendezvous::decode_from_reader(r)?,
|
|
||||||
),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
RelayCmd::INTRODUCE1 => {
|
|
||||||
RelayMsg::Introduce1(onion_service::Introduce1::decode_from_reader(r)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO hs
|
|
||||||
// #[cfg(feature = "onion-service")]
|
|
||||||
// RelayCmd::RENDEZVOUS1 => todo!(),
|
|
||||||
// #[cfg(feature = "onion-service")]
|
|
||||||
// RelayCmd::RENDEZVOUS2 => todo!(),
|
|
||||||
// #[cfg(feature = "onion-service")]
|
|
||||||
// RelayCmd::INTRO_ESTABLISHED => todo!(),
|
|
||||||
// #[cfg(feature = "onion-service")]
|
|
||||||
// RelayCmd::RENDEZVOUS_ESTABLISHED => todo!(),
|
|
||||||
// #[cfg(feature = "onion-service")]
|
|
||||||
// RelayCmd::INTRODUCE_ACK => todo!(),
|
|
||||||
_ => RelayMsg::Unrecognized(Unrecognized::decode_with_cmd(c, r)?),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::missing_panics_doc)] // TODO hs
|
|
||||||
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
|
||||||
use RelayMsg::*;
|
|
||||||
match self {
|
|
||||||
Begin(b) => b.encode_onto(w),
|
|
||||||
Data(b) => b.encode_onto(w),
|
|
||||||
End(b) => b.encode_onto(w),
|
|
||||||
Connected(b) => b.encode_onto(w),
|
|
||||||
Sendme(b) => b.encode_onto(w),
|
|
||||||
Extend(b) => b.encode_onto(w),
|
|
||||||
Extended(b) => b.encode_onto(w),
|
|
||||||
Extend2(b) => b.encode_onto(w),
|
|
||||||
Extended2(b) => b.encode_onto(w),
|
|
||||||
Truncate(b) => b.encode_onto(w),
|
|
||||||
Truncated(b) => b.encode_onto(w),
|
|
||||||
Drop(b) => b.encode_onto(w),
|
|
||||||
Resolve(b) => b.encode_onto(w),
|
|
||||||
Resolved(b) => b.encode_onto(w),
|
|
||||||
BeginDir(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
ConnectUdp(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
ConnectedUdp(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "experimental-udp")]
|
|
||||||
Datagram(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
EstablishIntro(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
EstablishRendezvous(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Introduce1(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Introduce2(b) => b.encode_onto(w),
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Rendezvous1(_) => todo!(), // TODO hs
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
Rendezvous2(_) => todo!(), // TODO hs
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
IntroEstablished(_) => todo!(), // TODO hs
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
RendEstablished => todo!(), // TODO hs
|
|
||||||
#[cfg(feature = "onion-service")]
|
|
||||||
IntroduceAck(_) => todo!(), // TODO hs
|
|
||||||
|
|
||||||
Unrecognized(b) => b.encode_onto(w),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RelayMsg {
|
impl RelayMsg {
|
||||||
/// Return the stream command associated with this message.
|
/// Return the stream command associated with this message.
|
||||||
pub fn cmd(&self) -> RelayCmd {
|
pub fn cmd(&self) -> RelayCmd {
|
||||||
|
@ -1357,6 +1212,7 @@ macro_rules! empty_body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) use empty_body;
|
||||||
|
|
||||||
empty_body! {
|
empty_body! {
|
||||||
/// A padding message, which is always ignored.
|
/// A padding message, which is always ignored.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Encoding and decoding for relay messages related to onion services.
|
//! Encoding and decoding for relay messages related to onion services.
|
||||||
|
|
||||||
#![allow(dead_code)] // TODO hs: remove.
|
#![allow(dead_code, unused_variables)] // TODO hs: remove.
|
||||||
|
|
||||||
// TODO hs design: We need to discuss how we want to handle extensions in these
|
// TODO hs design: We need to discuss how we want to handle extensions in these
|
||||||
// cells: extensions are used all over the protocol, and it would be nice to be
|
// cells: extensions are used all over the protocol, and it would be nice to be
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
// TODO hs: we'll need accessors for the useful fields in all these types.
|
// TODO hs: we'll need accessors for the useful fields in all these types.
|
||||||
|
|
||||||
use super::msg;
|
use super::msg::{self, Body};
|
||||||
use caret::caret_int;
|
use caret::caret_int;
|
||||||
use tor_bytes::{EncodeError, EncodeResult, Error as BytesError, Readable, Result, Writeable};
|
use tor_bytes::{EncodeError, EncodeResult, Error as BytesError, Readable, Result, Writeable};
|
||||||
use tor_bytes::{Reader, Writer};
|
use tor_bytes::{Reader, Writer};
|
||||||
|
@ -385,6 +385,21 @@ pub struct Rendezvous1 {
|
||||||
/// The message to send the client.
|
/// The message to send the client.
|
||||||
message: Vec<u8>,
|
message: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Body for Rendezvous1 {
|
||||||
|
fn into_message(self) -> msg::RelayMsg {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A message sent from the rendezvous point to the client, telling it about the
|
/// A message sent from the rendezvous point to the client, telling it about the
|
||||||
/// onion service's message.
|
/// onion service's message.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -393,6 +408,20 @@ pub struct Rendezvous2 {
|
||||||
message: Vec<u8>,
|
message: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Body for Rendezvous2 {
|
||||||
|
fn into_message(self) -> msg::RelayMsg {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reply sent from the introduction point to the onion service, telling it that
|
/// Reply sent from the introduction point to the onion service, telling it that
|
||||||
/// an introduction point is now established.
|
/// an introduction point is now established.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -404,6 +433,20 @@ pub struct IntroEstablished {
|
||||||
extensions: Vec<IntroEstExtension>,
|
extensions: Vec<IntroEstExtension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Body for IntroEstablished {
|
||||||
|
fn into_message(self) -> msg::RelayMsg {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An extension included in an [`IntroEstablished`] message.
|
/// An extension included in an [`IntroEstablished`] message.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -421,3 +464,22 @@ pub struct IntroduceAck {
|
||||||
status_code: u16,
|
status_code: u16,
|
||||||
// TODO hs: add extensions.
|
// TODO hs: add extensions.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Body for IntroduceAck {
|
||||||
|
fn into_message(self) -> msg::RelayMsg {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super::msg::empty_body! {
|
||||||
|
/// Acknowledges an EstablishRendezvous message.
|
||||||
|
pub struct RendezvousEstablished {}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue