|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
use crate::{
|
|
|
|
|
client::{Client, ReconnectStrategy, UntypedClient},
|
|
|
|
|
common::{ConnectionId, FramedTransport, InmemoryTransport},
|
|
|
|
|
common::{ConnectionId, FramedTransport, InmemoryTransport, UntypedRequest},
|
|
|
|
|
manager::data::{ManagerRequest, ManagerResponse},
|
|
|
|
|
};
|
|
|
|
|
use log::*;
|
|
|
|
@ -9,20 +9,18 @@ use std::{
|
|
|
|
|
io,
|
|
|
|
|
ops::{Deref, DerefMut},
|
|
|
|
|
};
|
|
|
|
|
use tokio::{sync::oneshot, task::JoinHandle};
|
|
|
|
|
use tokio::task::JoinHandle;
|
|
|
|
|
|
|
|
|
|
/// Represents a raw channel between a manager client and server. Underneath, this routes incoming
|
|
|
|
|
/// and outgoing data from a proxied server to an inmemory transport.
|
|
|
|
|
pub struct RawChannel {
|
|
|
|
|
transport: InmemoryTransport,
|
|
|
|
|
forward_task: JoinHandle<()>,
|
|
|
|
|
mailbox_task: JoinHandle<()>,
|
|
|
|
|
transport: FramedTransport<InmemoryTransport>,
|
|
|
|
|
task: JoinHandle<()>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RawChannel {
|
|
|
|
|
pub fn abort(&self) {
|
|
|
|
|
self.forward_task.abort();
|
|
|
|
|
self.mailbox_task.abort();
|
|
|
|
|
self.task.abort();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Consumes this channel, returning a typed client wrapping the transport.
|
|
|
|
@ -37,10 +35,7 @@ impl RawChannel {
|
|
|
|
|
T: Send + Sync + Serialize + 'static,
|
|
|
|
|
U: Send + Sync + DeserializeOwned + 'static,
|
|
|
|
|
{
|
|
|
|
|
Client::spawn_inmemory(
|
|
|
|
|
FramedTransport::plain(self.transport),
|
|
|
|
|
ReconnectStrategy::Fail,
|
|
|
|
|
)
|
|
|
|
|
Client::spawn_inmemory(self.transport, ReconnectStrategy::Fail)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Consumes this channel, returning an untyped client wrapping the transport.
|
|
|
|
@ -51,15 +46,12 @@ impl RawChannel {
|
|
|
|
|
/// performed during separate connection and this merely wraps an inmemory transport that maps
|
|
|
|
|
/// to the primary connection.
|
|
|
|
|
pub fn into_untyped_client(self) -> UntypedClient {
|
|
|
|
|
UntypedClient::spawn_inmemory(
|
|
|
|
|
FramedTransport::plain(self.transport),
|
|
|
|
|
ReconnectStrategy::Fail,
|
|
|
|
|
)
|
|
|
|
|
UntypedClient::spawn_inmemory(self.transport, ReconnectStrategy::Fail)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Deref for RawChannel {
|
|
|
|
|
type Target = InmemoryTransport;
|
|
|
|
|
type Target = FramedTransport<InmemoryTransport>;
|
|
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
&self.transport
|
|
|
|
@ -100,56 +92,60 @@ impl RawChannel {
|
|
|
|
|
}?;
|
|
|
|
|
|
|
|
|
|
// Spawn our channel proxy transport
|
|
|
|
|
let (tx, mut rx, transport) = InmemoryTransport::make(1);
|
|
|
|
|
let (channel_close_tx, mut channel_close_rx) = oneshot::channel();
|
|
|
|
|
let mailbox_task = tokio::spawn(async move {
|
|
|
|
|
while let Some(response) = mailbox.next().await {
|
|
|
|
|
match response.payload {
|
|
|
|
|
ManagerResponse::Channel { data, .. } => {
|
|
|
|
|
if let Err(x) = tx.send(data).await {
|
|
|
|
|
error!("[Conn {connection_id} :: Chan {channel_id}] {x}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ManagerResponse::ChannelClosed { .. } => {
|
|
|
|
|
let _ = channel_close_tx.send(());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_ => continue,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
let (mut proxy, transport) = FramedTransport::pair(1);
|
|
|
|
|
|
|
|
|
|
let mut manager_channel = client.clone_channel();
|
|
|
|
|
let forward_task = tokio::spawn(async move {
|
|
|
|
|
let task = tokio::spawn(async move {
|
|
|
|
|
loop {
|
|
|
|
|
tokio::select! {
|
|
|
|
|
_ = &mut channel_close_rx => { break }
|
|
|
|
|
data = rx.recv() => {
|
|
|
|
|
match data {
|
|
|
|
|
Some(data) => {
|
|
|
|
|
maybe_response = mailbox.next() => {
|
|
|
|
|
if maybe_response.is_none() {
|
|
|
|
|
debug!("[Conn {connection_id} :: Chan {channel_id}] Closing from no more responses");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
match maybe_response.unwrap().payload {
|
|
|
|
|
ManagerResponse::Channel { response, .. } => {
|
|
|
|
|
if let Err(x) = proxy.write_frame_for(&response).await {
|
|
|
|
|
error!(
|
|
|
|
|
"[Conn {connection_id} :: Chan {channel_id}] Write response failed: {x}"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ManagerResponse::ChannelClosed { .. } => {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_ => continue,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
result = proxy.read_frame_as::<UntypedRequest>() => {
|
|
|
|
|
match result {
|
|
|
|
|
Ok(Some(request)) => {
|
|
|
|
|
// NOTE: In this situation, we do not expect a response to this
|
|
|
|
|
// request (even if the server sends something back)
|
|
|
|
|
if let Err(x) = manager_channel
|
|
|
|
|
.fire(ManagerRequest::Channel {
|
|
|
|
|
id: channel_id,
|
|
|
|
|
data,
|
|
|
|
|
request,
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
{
|
|
|
|
|
error!("[Conn {connection_id} :: Chan {channel_id}] {x}");
|
|
|
|
|
error!("[Conn {connection_id} :: Chan {channel_id}] Forward failed: {x}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => break,
|
|
|
|
|
Ok(None) => {
|
|
|
|
|
debug!("[Conn {connection_id} :: Chan {channel_id}] Closing from no more requests");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
Err(x) => {
|
|
|
|
|
error!("[Conn {connection_id} :: Chan {channel_id}] Read request failed: {x}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Ok(RawChannel {
|
|
|
|
|
transport,
|
|
|
|
|
forward_task,
|
|
|
|
|
mailbox_task,
|
|
|
|
|
})
|
|
|
|
|
Ok(RawChannel { transport, task })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|