/// Performs negotiation, returning the stream if successful
///
/// If the negotiation task is dropped, the stream is dropped in an indeterminate state.
/// In scenarios involving an owned stream, this will drop the stream, otherwise the
/// other end of the stream may be at an unknown point in the protocol. As such, any
/// timeout mechanism here must not expect to resume the stream after a ref drop.
Performs negotiation, returning the stream if successful
If the negotiation task is dropped, the stream is dropped in an indeterminate state.
In scenarios involving an owned stream, this will drop the stream, otherwise the
other end of the stream may be at an unknown point in the protocol. As such, any
timeout mechanism here must not expect to resume the stream after a ref drop.
Performs negotiation returning the stream if successful If the negotiation task is dropped the stream is dropped in an indeterminate state . In scenarios involving an owned stream this will drop the stream otherwise the other end of the stream may be at an unknown point in the protocol . As such any timeout mechanism here must not expect to resume the stream after a ref drop .
pub fn negotiate<'a, S: TunnelStream + Send + 'a>(
    &self,
    mut link: S,
    tunnel_id: TunnelId,
  ) -> BoxFuture<'a, Result<(S, RouteAddress, ArcService), NegotiationError>> {
    const CURRENT_PROTOCOL_VERSION: u8 = 0u8;
    let service_registry = Arc::clone(&self.service_registry);
    async move {
      tracing::trace!("performing negotiation protocol handshake");
      let remote_version = protocol_magic(&mut link, CURRENT_PROTOCOL_VERSION).await?;
      // TODO: Consider adding a confirmation for negotiation protocol acceptance here
      if remote_version > 0 {
        // This should map to multiple supported versions, where possible
        tracing::trace!(
          version = remote_version,
          "unsupported remote protocol version"
        );
        return Err(NegotiationError::UnsupportedProtocolVersion);
      }
      let addr = crate::util::framed::read_frame_vec(&mut link)
        .await
        .map_err(|_| NegotiationError::ProtocolViolation)?; // Address must be sent as a frame in v0
      let addr = String::from_utf8(addr).map_err(|_| NegotiationError::ProtocolViolation)?; // Addresses must be valid UTF-8
      tracing::trace!("searching service registry for address handlers");
      let found = service_registry.find_service(&addr, &tunnel_id);
      match found {
        None => {
          // Write refusal
          // v0 calls for a non-zero u8 to be written to the stream to refuse an address
          tracing::trace!("refusing address");
          link
            .write_u8(1)
            .await
            .map_err(|_| NegotiationError::WriteError)?;
          Err(NegotiationError::Refused)
        }
        Some(service) => {
          // Write acceptance
          // v0 calls for a 0u8 to be written to the stream to accept an address
          tracing::trace!("accepting address");
          link
            .write_u8(0)
            .await
            .map_err(|_| NegotiationError::WriteError)?;
          Ok((link, addr, service))
        }
      }
    }
    .instrument(tracing::trace_span!("Service"))
    .boxed()
  }
pub fn negotiate < ' a , S : TunnelStream + Send + ' a > ( & self , mut link : S , tunnel_id : TunnelId , ) -> BoxFuture < ' a , Result < ( S , RouteAddress , ArcService ) , NegotiationError > > { const CURRENT_PROTOCOL_VERSION : u8 = 0u8 ; let service_registry = Arc :: clone ( & self . service_registry ) ; async move { tracing :: trace ! ( " " ) ; let remote_version = protocol_magic ( & mut link , CURRENT_PROTOCOL_VERSION ) . await ? ; // TODO: Consider adding a confirmation for negotiation protocol acceptance here if remote_version > 0 { // This should map to multiple supported versions, where possible tracing :: trace ! ( version remote_version " " ) ; return Err ( NegotiationError :: UnsupportedProtocolVersion ) ; } let addr = crate :: util :: framed :: read_frame_vec ( & mut link ) . await . map_err ( | _ | NegotiationError :: ProtocolViolation ) ? ; // Address must be sent as a frame in v0 let addr = String :: from_utf8 ( addr ) . map_err ( | _ | NegotiationError :: ProtocolViolation ) ? ; // Addresses must be valid UTF-8 tracing :: trace ! ( " " ) ; let found = service_registry . find_service ( & addr , & tunnel_id ) ; match found { None => { // Write refusal // v0 calls for a non-zero u8 to be written to the stream to refuse an address tracing :: trace ! ( " " ) ; link . write_u8 ( 1 ) . await . map_err ( | _ | NegotiationError :: WriteError ) ? ; Err ( NegotiationError :: Refused ) } Some ( service ) => { // Write acceptance // v0 calls for a 0u8 to be written to the stream to accept an address tracing :: trace ! ( " " ) ; link . write_u8 ( 0 ) . await . map_err ( | _ | NegotiationError :: WriteError ) ? ; Ok ( ( link , addr , service ) ) } } } . instrument ( tracing :: trace_span ! ( " " ) ) . boxed ( ) }
Performs negotiation, returning the stream if successful
If the negotiation task is dropped, the stream is dropped in an indeterminate state.
Performs negotiation returning the stream if successful If the negotiation task is dropped the stream is dropped in an indeterminate state .
&self
link
S
tunnel_id
TunnelId