use crate::{event::TransportEvent, packet::Packet, SessionId};
use futures::{Stream, StreamExt};
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::sync::{broadcast, mpsc};
use tokio_stream::wrappers::{errors::BroadcastStreamRecvError, BroadcastStream};
pub struct EventStream {
inner: BroadcastStream<TransportEvent>,
session_filter: Option<SessionId>,
}
impl EventStream {
pub fn new(receiver: broadcast::Receiver<TransportEvent>) -> Self {
Self {
inner: BroadcastStream::new(receiver),
session_filter: None,
}
}
#[deprecated(
since = "1.0.7",
note = "session filtering drops MessageReceived/ConnectionClosed; filter at the ServerEvent layer instead"
)]
pub fn with_session_filter(
receiver: broadcast::Receiver<TransportEvent>,
session_id: SessionId,
) -> Self {
Self {
inner: BroadcastStream::new(receiver),
session_filter: Some(session_id),
}
}
#[deprecated(
since = "1.0.7",
note = "session filtering drops MessageReceived/ConnectionClosed; filter at the ServerEvent layer instead"
)]
pub fn filter_session(mut self, session_id: SessionId) -> Self {
self.session_filter = Some(session_id);
self
}
pub async fn next_connection_event(&mut self) -> Option<TransportEvent> {
while let Some(result) = self.inner.next().await {
if let Ok(event) = result {
if self.should_emit_event(&event) && event.is_connection_event() {
return Some(event);
}
}
}
None
}
pub async fn next_data_event(&mut self) -> Option<TransportEvent> {
while let Some(result) = self.inner.next().await {
if let Ok(event) = result {
if self.should_emit_event(&event) && event.is_data_event() {
return Some(event);
}
}
}
None
}
pub async fn next_error_event(&mut self) -> Option<TransportEvent> {
while let Some(result) = self.inner.next().await {
if let Ok(event) = result {
if self.should_emit_event(&event) && event.is_error_event() {
return Some(event);
}
}
}
None
}
fn should_emit_event(&self, event: &TransportEvent) -> bool {
match self.session_filter {
Some(filter_session_id) => match event.session_id() {
Some(event_session_id) => event_session_id == filter_session_id,
None => false,
},
None => true, }
}
}
impl Stream for EventStream {
type Item = TransportEvent;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.inner).poll_next(cx) {
Poll::Ready(Some(Ok(event))) => {
if self.should_emit_event(&event) {
return Poll::Ready(Some(event));
}
}
Poll::Ready(Some(Err(BroadcastStreamRecvError::Lagged(skipped)))) => {
tracing::warn!(
"[STREAM] EventStream lagged, skipped {} transport events",
skipped
);
continue;
}
Poll::Ready(None) => {
return Poll::Ready(None);
}
Poll::Pending => {
return Poll::Pending;
}
}
}
}
}
pub struct GenericReceiver<T> {
receiver: mpsc::Receiver<T>,
#[allow(dead_code)]
recv_future: Option<Pin<Box<dyn std::future::Future<Output = Option<T>> + Send>>>,
}
impl<T: Send + 'static> GenericReceiver<T> {
pub fn new(receiver: mpsc::Receiver<T>) -> Self {
Self {
receiver,
recv_future: None,
}
}
pub fn try_recv(&mut self) -> Result<T, mpsc::error::TryRecvError> {
self.receiver.try_recv()
}
pub async fn recv(&mut self) -> Option<T> {
self.receiver.recv().await
}
pub fn close(&mut self) {
self.receiver.close();
}
}
impl<T: Send + 'static> Stream for GenericReceiver<T> {
type Item = T;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.receiver.poll_recv(cx)
}
}
pub struct PacketStream {
event_stream: EventStream,
}
impl PacketStream {
pub fn new(receiver: broadcast::Receiver<TransportEvent>) -> Self {
Self {
event_stream: EventStream::new(receiver),
}
}
#[deprecated(
since = "1.0.7",
note = "session filtering drops MessageReceived/ConnectionClosed; filter at the ServerEvent layer instead"
)]
#[allow(deprecated)]
pub fn with_session_filter(
receiver: broadcast::Receiver<TransportEvent>,
session_id: SessionId,
) -> Self {
Self {
event_stream: EventStream::with_session_filter(receiver, session_id),
}
}
pub async fn next_packet(&mut self) -> Option<Packet> {
while let Some(event) = self.event_stream.next().await {
if let crate::event::TransportEvent::MessageReceived(packet) = event {
return Some(packet);
}
}
None
}
}
impl Stream for PacketStream {
type Item = Packet;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.event_stream).poll_next(cx) {
Poll::Ready(Some(crate::event::TransportEvent::MessageReceived(packet))) => {
return Poll::Ready(Some(packet));
}
Poll::Ready(Some(_)) => {
continue;
}
Poll::Ready(None) => {
return Poll::Ready(None);
}
Poll::Pending => {
return Poll::Pending;
}
}
}
}
}
pub struct ConnectionStream {
event_stream: EventStream,
}
impl ConnectionStream {
pub fn new(receiver: broadcast::Receiver<TransportEvent>) -> Self {
Self {
event_stream: EventStream::new(receiver),
}
}
pub async fn next_connection(&mut self) -> Option<ConnectionEvent> {
while let Some(event) = self.event_stream.next().await {
match event {
TransportEvent::ConnectionEstablished { info } => {
return Some(ConnectionEvent::Established { info });
}
TransportEvent::ConnectionClosed { reason } => {
return Some(ConnectionEvent::Closed { reason });
}
_ => continue,
}
}
None
}
}
impl Stream for ConnectionStream {
type Item = ConnectionEvent;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.event_stream).poll_next(cx) {
Poll::Ready(Some(TransportEvent::ConnectionEstablished { info })) => {
return Poll::Ready(Some(ConnectionEvent::Established { info }));
}
Poll::Ready(Some(TransportEvent::ConnectionClosed { reason })) => {
return Poll::Ready(Some(ConnectionEvent::Closed { reason }));
}
Poll::Ready(Some(_)) => {
continue;
}
Poll::Ready(None) => {
return Poll::Ready(None);
}
Poll::Pending => {
return Poll::Pending;
}
}
}
}
}
#[derive(Debug, Clone)]
pub enum ConnectionEvent {
Established {
info: crate::command::ConnectionInfo,
},
Closed { reason: crate::CloseReason },
}
pub struct StreamFactory;
impl StreamFactory {
pub fn event_stream(receiver: broadcast::Receiver<TransportEvent>) -> EventStream {
EventStream::new(receiver)
}
pub fn packet_stream(receiver: broadcast::Receiver<TransportEvent>) -> PacketStream {
PacketStream::new(receiver)
}
pub fn connection_stream(receiver: broadcast::Receiver<TransportEvent>) -> ConnectionStream {
ConnectionStream::new(receiver)
}
#[deprecated(
since = "1.0.7",
note = "session filtering drops MessageReceived/ConnectionClosed; filter at the ServerEvent layer instead"
)]
#[allow(deprecated)]
pub fn session_event_stream(
receiver: broadcast::Receiver<TransportEvent>,
session_id: SessionId,
) -> EventStream {
EventStream::with_session_filter(receiver, session_id)
}
#[deprecated(
since = "1.0.7",
note = "session filtering drops MessageReceived/ConnectionClosed; filter at the ServerEvent layer instead"
)]
#[allow(deprecated)]
pub fn session_packet_stream(
receiver: broadcast::Receiver<TransportEvent>,
session_id: SessionId,
) -> PacketStream {
PacketStream::with_session_filter(receiver, session_id)
}
pub fn client_event_stream(
receiver: tokio::sync::broadcast::Receiver<crate::event::TransportEvent>,
) -> ClientEventStream {
ClientEventStream::new(receiver)
}
}
pub struct StreamCombinator;
impl StreamCombinator {
pub fn merge_event_streams(streams: Vec<EventStream>) -> impl Stream<Item = TransportEvent> {
futures::stream::select_all(streams)
}
pub fn events_to_packets(event_stream: EventStream) -> impl Stream<Item = Packet> {
event_stream.filter_map(|event| async move {
match event {
crate::event::TransportEvent::MessageReceived(packet) => Some(packet),
_ => None,
}
})
}
pub fn events_to_connections(event_stream: EventStream) -> impl Stream<Item = ConnectionEvent> {
event_stream.filter_map(|event| async move {
match event {
TransportEvent::ConnectionEstablished { info } => {
Some(ConnectionEvent::Established { info })
}
TransportEvent::ConnectionClosed { reason } => {
Some(ConnectionEvent::Closed { reason })
}
_ => None,
}
})
}
}
pub trait ReceiverExt {
fn into_event_stream(self) -> EventStream;
fn into_packet_stream(self) -> PacketStream;
fn into_connection_stream(self) -> ConnectionStream;
}
impl ReceiverExt for broadcast::Receiver<TransportEvent> {
fn into_event_stream(self) -> EventStream {
EventStream::new(self)
}
fn into_packet_stream(self) -> PacketStream {
PacketStream::new(self)
}
fn into_connection_stream(self) -> ConnectionStream {
ConnectionStream::new(self)
}
}
pub struct ClientEventStream {
inner: tokio::sync::broadcast::Receiver<crate::event::TransportEvent>,
}
impl ClientEventStream {
pub fn new(receiver: tokio::sync::broadcast::Receiver<crate::event::TransportEvent>) -> Self {
Self { inner: receiver }
}
pub async fn next(
&mut self,
) -> Result<crate::event::ClientEvent, crate::error::TransportError> {
loop {
match self.inner.recv().await {
Ok(transport_event) => {
if let Some(client_event) =
crate::event::ClientEvent::from_transport_event(transport_event)
{
return Ok(client_event);
}
}
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
return Err(crate::error::TransportError::connection_error(
"Event stream closed",
false,
));
}
Err(tokio::sync::broadcast::error::RecvError::Lagged(skipped)) => {
tracing::warn!(
"[STREAM] ClientEventStream lagged, skipped {} transport events",
skipped
);
continue;
}
}
}
}
pub fn try_next(
&mut self,
) -> Result<Option<crate::event::ClientEvent>, crate::error::TransportError> {
loop {
match self.inner.try_recv() {
Ok(transport_event) => {
if let Some(client_event) =
crate::event::ClientEvent::from_transport_event(transport_event)
{
return Ok(Some(client_event));
}
}
Err(tokio::sync::broadcast::error::TryRecvError::Empty) => {
return Ok(None);
}
Err(tokio::sync::broadcast::error::TryRecvError::Closed) => {
return Err(crate::error::TransportError::connection_error(
"Event stream closed",
false,
));
}
Err(tokio::sync::broadcast::error::TryRecvError::Lagged(skipped)) => {
tracing::warn!(
"[STREAM] ClientEventStream lagged, skipped {} transport events",
skipped
);
continue;
}
}
}
}
}