use crate::stream::ConnectionInfoProvider;
use std::fmt::{Debug, Display};
use std::io;
use std::net::SocketAddr;
use std::time::Duration;
pub trait Endpoint: ConnectionInfoProvider {
type Target;
fn create_target(&mut self, addr: SocketAddr) -> io::Result<Option<Self::Target>>;
fn can_recreate(&mut self, _reason: DisconnectReason) -> bool {
true
}
fn can_auto_disconnect(&mut self) -> bool {
true
}
}
pub trait Context {}
pub trait EndpointWithContext<C>: ConnectionInfoProvider {
type Target;
fn create_target(&mut self, addr: SocketAddr, context: &mut C) -> io::Result<Option<Self::Target>>;
fn can_recreate(&mut self, _reason: DisconnectReason, _context: &mut C) -> bool {
true
}
fn can_auto_disconnect(&mut self, _context: &mut C) -> bool {
true
}
}
pub enum DisconnectReason {
AutoDisconnect(Duration),
IO(io::Error),
}
impl Display for DisconnectReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DisconnectReason::AutoDisconnect(ttl) => {
write!(f, "auto-disconnect after ")?;
ttl.fmt(f)
}
DisconnectReason::IO(err) => {
write!(f, "{err}")
}
}
}
}
impl DisconnectReason {
pub(crate) fn auto_disconnect(ttl: Duration) -> DisconnectReason {
DisconnectReason::AutoDisconnect(ttl)
}
pub(crate) fn other(err: io::Error) -> DisconnectReason {
DisconnectReason::IO(err)
}
}
#[cfg(all(feature = "ext", feature = "ws", any(feature = "rustls", feature = "openssl")))]
pub mod ws {
use std::io;
use std::io::{Read, Write};
use std::net::SocketAddr;
use crate::service::endpoint::{DisconnectReason, Endpoint, EndpointWithContext};
use crate::stream::ConnectionInfoProvider;
use crate::stream::tls::TlsStream;
use crate::ws::Websocket;
pub type TlsWebsocket<S> = Websocket<TlsStream<S>>;
pub trait TlsWebsocketEndpoint: ConnectionInfoProvider {
type Stream: Read + Write;
fn create_websocket(&mut self, addr: SocketAddr) -> io::Result<Option<Websocket<TlsStream<Self::Stream>>>>;
fn can_recreate(&mut self, _reason: DisconnectReason) -> bool {
true
}
fn can_auto_disconnect(&mut self) -> bool {
true
}
}
impl<T> Endpoint for T
where
T: TlsWebsocketEndpoint,
{
type Target = Websocket<TlsStream<T::Stream>>;
#[inline]
fn create_target(&mut self, addr: SocketAddr) -> io::Result<Option<Self::Target>> {
self.create_websocket(addr)
}
#[inline]
fn can_recreate(&mut self, reason: DisconnectReason) -> bool {
self.can_recreate(reason)
}
#[inline]
fn can_auto_disconnect(&mut self) -> bool {
self.can_auto_disconnect()
}
}
pub trait TlsWebsocketEndpointWithContext<C>: ConnectionInfoProvider {
type Stream: Read + Write;
fn create_websocket(
&mut self,
addr: SocketAddr,
ctx: &mut C,
) -> io::Result<Option<Websocket<TlsStream<Self::Stream>>>>;
fn can_recreate(&mut self, _reason: DisconnectReason, _ctx: &mut C) -> bool {
true
}
fn can_auto_disconnect(&mut self, _ctx: &mut C) -> bool {
true
}
}
impl<T, C> EndpointWithContext<C> for T
where
T: TlsWebsocketEndpointWithContext<C>,
{
type Target = Websocket<TlsStream<T::Stream>>;
#[inline]
fn create_target(&mut self, addr: SocketAddr, context: &mut C) -> io::Result<Option<Self::Target>> {
self.create_websocket(addr, context)
}
#[inline]
fn can_recreate(&mut self, reason: DisconnectReason, context: &mut C) -> bool {
self.can_recreate(reason, context)
}
#[inline]
fn can_auto_disconnect(&mut self, context: &mut C) -> bool {
self.can_auto_disconnect(context)
}
}
}