Implemented TCP listener
This commit is contained in:
87
d3270d/src/gen_connection.rs
Normal file
87
d3270d/src/gen_connection.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use crate::arbiter::{ArbiterHandle, ArbiterHandleRequester};
|
||||
use d3270_common::b3270::indication::RunResult;
|
||||
use d3270_common::b3270::operation::Run;
|
||||
use d3270_common::b3270::{Indication, Operation};
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::stream::StreamExt;
|
||||
use futures::FutureExt;
|
||||
use std::future::{poll_fn, Future};
|
||||
use std::pin::Pin;
|
||||
use std::task::{ready, Context, Poll};
|
||||
use tokio::sync::oneshot;
|
||||
use tracing::warn;
|
||||
|
||||
pub struct GenConnection {
|
||||
handle: ArbiterHandle,
|
||||
waiting_actions: FuturesUnordered<ReplaceTag>,
|
||||
}
|
||||
|
||||
struct ReplaceTag {
|
||||
tag: Option<String>,
|
||||
rcvr: oneshot::Receiver<RunResult>,
|
||||
}
|
||||
|
||||
impl Future for ReplaceTag {
|
||||
type Output = Option<Indication>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(ready!(self.rcvr.poll_unpin(cx)).ok().map(|run_res| {
|
||||
Indication::RunResult(RunResult {
|
||||
r_tag: self.tag.take(),
|
||||
..run_res
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl GenConnection {
|
||||
pub async fn new(ahr: ArbiterHandleRequester) -> anyhow::Result<Self> {
|
||||
let handle = ahr.connect().await?;
|
||||
Ok(Self {
|
||||
handle,
|
||||
waiting_actions: FuturesUnordered::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn handle_client_line(&mut self, line: String) -> anyhow::Result<()> {
|
||||
let op = serde_json::from_str(&line)?;
|
||||
match op {
|
||||
Operation::Run(Run { actions, r_tag, .. }) => {
|
||||
let rcvr = self.handle.send_actions(actions).await?;
|
||||
self.waiting_actions.push(ReplaceTag { tag: r_tag, rcvr });
|
||||
}
|
||||
_ => warn!(json = line, "Unsupported operation from client"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn poll_indication(&mut self, cx: &mut Context) -> Poll<Option<Indication>> {
|
||||
let mut any_can_continue = false;
|
||||
|
||||
match self.waiting_actions.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(ind)) => {
|
||||
return Poll::Ready(ind);
|
||||
}
|
||||
Poll::Ready(None) => {}
|
||||
Poll::Pending => any_can_continue = true,
|
||||
}
|
||||
|
||||
match self.handle.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(ind)) => {
|
||||
return Poll::Ready(Some(ind));
|
||||
}
|
||||
Poll::Ready(None) => {}
|
||||
Poll::Pending => any_can_continue = true,
|
||||
}
|
||||
|
||||
if any_can_continue {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn next_indication(&mut self) -> Option<Indication> {
|
||||
poll_fn(|cx| self.poll_indication(cx)).await
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user