use std::collections::HashMap;
use std::io;
use futures::sync::{mpsc, oneshot};
use futures::{Async, AsyncSink, Future, IntoFuture, Poll, Sink, StartSend, Stream};
use rmpv::Value;
use tokio;
use tokio::codec::{Decoder, Framed};
use tokio::io::{AsyncRead, AsyncWrite};
use codec::Codec;
use message::Response as MsgPackResponse;
use message::{Message, Notification, Request};
pub trait IntoStaticFuture {
type Future: Future<Item = Self::Item, Error = Self::Error> + 'static + Send;
type Item;
type Error;
fn into_static_future(self) -> Self::Future;
}
impl<F: IntoFuture> IntoStaticFuture for F
where
<F as IntoFuture>::Future: 'static + Send,
{
type Future = <F as IntoFuture>::Future;
type Item = <F as IntoFuture>::Item;
type Error = <F as IntoFuture>::Error;
fn into_static_future(self) -> Self::Future {
self.into_future()
}
}
pub trait Service: Send {
type RequestFuture: IntoStaticFuture<Item = Value, Error = Value>;
fn handle_request(&mut self, method: &str, params: &[Value]) -> Self::RequestFuture;
fn handle_notification(&mut self, method: &str, params: &[Value]);
}
pub trait ServiceWithClient {
type RequestFuture: IntoStaticFuture<Item = Value, Error = Value>;
fn handle_request(
&mut self,
client: &mut Client,
method: &str,
params: &[Value],
) -> Self::RequestFuture;
fn handle_notification(&mut self, client: &mut Client, method: &str, params: &[Value]);
}
impl<S: Service> ServiceWithClient for S {
type RequestFuture = <S as Service>::RequestFuture;
fn handle_request(
&mut self,
_client: &mut Client,
method: &str,
params: &[Value],
) -> Self::RequestFuture {
self.handle_request(method, params)
}
fn handle_notification(&mut self, _client: &mut Client, method: &str, params: &[Value]) {
self.handle_notification(method, params);
}
}
struct Server<S: ServiceWithClient> {
service: S,
pending_responses: mpsc::UnboundedReceiver<(u32, Result<Value, Value>)>,
response_sender: mpsc::UnboundedSender<(u32, Result<Value, Value>)>,
}
impl<S: ServiceWithClient> Server<S> {
fn new(service: S) -> Self {
let (send, recv) = mpsc::unbounded();
Server {
service,
pending_responses: recv,
response_sender: send,
}
}
fn send_responses<T: AsyncRead + AsyncWrite>(
&mut self,
sink: &mut Transport<T>,
) -> Poll<(), io::Error> {
while let Ok(poll) = self.pending_responses.poll() {
if let Async::Ready(Some((id, result))) = poll {
let msg = Message::Response(MsgPackResponse { id, result });
sink.start_send(msg).unwrap();
} else {
if let Async::Ready(None) = poll {
panic!("we store the sender, it can't be dropped");
}
return sink.poll_complete();
}
}
panic!("an UnboundedReceiver should never give an error");
}
fn spawn_request_worker<F: Future<Item = Value, Error = Value> + 'static + Send>(
&self,
id: u32,
mut f: F,
) {
match f.poll() {
Ok(Async::Ready(result)) => {
let _ = self.response_sender.unbounded_send((id, Ok(result)));
}
Err(e) => {
let _ = self.response_sender.unbounded_send((id, Err(e)));
}
Ok(Async::NotReady) => {
let send = self.response_sender.clone();
tokio::spawn(
f.then(move |result| send.unbounded_send((id, result)).map_err(|_| ())),
);
}
}
}
}
trait MessageHandler {
fn handle_incoming(&mut self, msg: Message);
fn send_outgoing<T: AsyncRead + AsyncWrite>(
&mut self,
sink: &mut Transport<T>,
) -> Poll<(), io::Error>;
fn is_finished(&self) -> bool {
false
}
}
type ResponseTx = oneshot::Sender<Result<Value, Value>>;
pub struct Response(oneshot::Receiver<Result<Value, Value>>);
type AckTx = oneshot::Sender<()>;
pub struct Ack(oneshot::Receiver<()>);
type RequestTx = mpsc::UnboundedSender<(Request, ResponseTx)>;
type RequestRx = mpsc::UnboundedReceiver<(Request, ResponseTx)>;
type NotificationTx = mpsc::UnboundedSender<(Notification, AckTx)>;
type NotificationRx = mpsc::UnboundedReceiver<(Notification, AckTx)>;
impl Future for Response {
type Item = Result<Value, Value>;
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.0.poll().map_err(|_| ())
}
}
impl Future for Ack {
type Item = ();
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.0.poll().map_err(|_| ())
}
}
struct InnerClient {
client_closed: bool,
request_id: u32,
requests_rx: RequestRx,
notifications_rx: NotificationRx,
pending_requests: HashMap<u32, ResponseTx>,
pending_notifications: Vec<AckTx>,
}
impl InnerClient {
fn new() -> (Self, Client) {
let (requests_tx, requests_rx) = mpsc::unbounded();
let (notifications_tx, notifications_rx) = mpsc::unbounded();
let client_proxy = Client::from_channels(requests_tx, notifications_tx);
let client = InnerClient {
client_closed: false,
request_id: 0,
requests_rx,
notifications_rx,
pending_requests: HashMap::new(),
pending_notifications: Vec::new(),
};
(client, client_proxy)
}
fn process_notifications<T: AsyncRead + AsyncWrite>(&mut self, stream: &mut Transport<T>) {
if self.client_closed {
return;
}
trace!("Polling client notifications channel");
loop {
match self.notifications_rx.poll() {
Ok(Async::Ready(Some((notification, ack_sender)))) => {
trace!("Got notification from client.");
stream.send(Message::Notification(notification));
self.pending_notifications.push(ack_sender);
}
Ok(Async::NotReady) => {
trace!("No new notification from client");
break;
}
Ok(Async::Ready(None)) => {
trace!("Client closed the notifications channel.");
self.client_closed = true;
break;
}
Err(()) => {
panic!("An error occured while polling the notifications channel.")
}
}
}
}
fn send_messages<T: AsyncRead + AsyncWrite>(
&mut self,
stream: &mut Transport<T>,
) -> Poll<(), io::Error> {
self.process_requests(stream);
self.process_notifications(stream);
match stream.poll_complete()? {
Async::Ready(()) => {
self.acknowledge_notifications();
Ok(Async::Ready(()))
}
Async::NotReady => Ok(Async::NotReady),
}
}
fn process_requests<T: AsyncRead + AsyncWrite>(&mut self, stream: &mut Transport<T>) {
if self.client_closed {
return;
}
trace!("Polling client requests channel");
loop {
match self.requests_rx.poll() {
Ok(Async::Ready(Some((mut request, response_sender)))) => {
self.request_id += 1;
trace!("Got request from client: {:?}", request);
request.id = self.request_id;
stream.send(Message::Request(request));
self.pending_requests
.insert(self.request_id, response_sender);
}
Ok(Async::Ready(None)) => {
trace!("Client closed the requests channel.");
self.client_closed = true;
break;
}
Ok(Async::NotReady) => {
trace!("No new request from client");
break;
}
Err(()) => {
panic!("An error occured while polling the requests channel");
}
}
}
}
fn process_response(&mut self, response: MsgPackResponse) {
if let Some(response_tx) = self.pending_requests.remove(&response.id) {
trace!("Forwarding response to the client.");
if let Err(e) = response_tx.send(response.result) {
warn!("Failed to send response to client: {:?}", e);
}
} else {
warn!("no pending request found for response {}", &response.id);
}
}
fn acknowledge_notifications(&mut self) {
for chan in self.pending_notifications.drain(..) {
trace!("Acknowledging notification.");
if let Err(e) = chan.send(()) {
warn!("Failed to send ack to client: {:?}", e);
}
}
}
}
struct Transport<T: AsyncRead + AsyncWrite>(Framed<T, Codec>);
impl<T> Transport<T>
where
T: AsyncRead + AsyncWrite,
{
fn send(&mut self, message: Message) {
trace!("Sending {:?}", message);
match self.start_send(message) {
Ok(AsyncSink::Ready) => return,
Ok(AsyncSink::NotReady(_message)) => panic!("The sink is full."),
Err(e) => panic!("An error occured while trying to send message: {}", e),
}
}
}
impl<T> Stream for Transport<T>
where
T: AsyncRead + AsyncWrite,
{
type Item = Message;
type Error = io::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.0.poll()
}
}
impl<T> Sink for Transport<T>
where
T: AsyncRead + AsyncWrite,
{
type SinkItem = Message;
type SinkError = io::Error;
fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
self.0.start_send(item)
}
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
self.0.poll_complete()
}
}
impl<S: Service> MessageHandler for Server<S> {
fn handle_incoming(&mut self, msg: Message) {
match msg {
Message::Request(req) => {
let f = self.service.handle_request(&req.method, &req.params);
self.spawn_request_worker(req.id, f.into_static_future());
}
Message::Notification(note) => {
self.service.handle_notification(¬e.method, ¬e.params);
}
Message::Response(_) => {
trace!("This endpoint doesn't handle responses, ignoring the msg.");
}
};
}
fn send_outgoing<T: AsyncRead + AsyncWrite>(
&mut self,
sink: &mut Transport<T>,
) -> Poll<(), io::Error> {
self.send_responses(sink)
}
}
impl MessageHandler for InnerClient {
fn handle_incoming(&mut self, msg: Message) {
trace!("Received {:?}", msg);
if let Message::Response(response) = msg {
self.process_response(response);
} else {
trace!("This endpoint only handles reponses, ignoring the msg.");
}
}
fn send_outgoing<T: AsyncRead + AsyncWrite>(
&mut self,
sink: &mut Transport<T>,
) -> Poll<(), io::Error> {
self.send_messages(sink)
}
fn is_finished(&self) -> bool {
self.client_closed
&& self.pending_requests.is_empty()
&& self.pending_notifications.is_empty()
}
}
struct ClientAndServer<S: ServiceWithClient> {
inner_client: InnerClient,
server: Server<S>,
client: Client,
}
impl<S: ServiceWithClient> MessageHandler for ClientAndServer<S> {
fn handle_incoming(&mut self, msg: Message) {
match msg {
Message::Request(req) => {
let f =
self.server
.service
.handle_request(&mut self.client, &req.method, &req.params);
self.server
.spawn_request_worker(req.id, f.into_static_future());
}
Message::Notification(note) => {
self.server.service.handle_notification(
&mut self.client,
¬e.method,
¬e.params,
);
}
Message::Response(response) => self.inner_client.process_response(response),
};
}
fn send_outgoing<T: AsyncRead + AsyncWrite>(
&mut self,
sink: &mut Transport<T>,
) -> Poll<(), io::Error> {
if let Async::Ready(_) = self.server.send_responses(sink)? {
self.inner_client.send_messages(sink)
} else {
Ok(Async::NotReady)
}
}
}
struct InnerEndpoint<MH: MessageHandler, T: AsyncRead + AsyncWrite> {
handler: MH,
stream: Transport<T>,
}
impl<MH: MessageHandler, T: AsyncRead + AsyncWrite> Future for InnerEndpoint<MH, T> {
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Async::NotReady = self.handler.send_outgoing(&mut self.stream)? {
trace!("Sink not yet flushed, waiting...");
return Ok(Async::NotReady);
}
trace!("Polling stream.");
while let Async::Ready(msg) = self.stream.poll()? {
if let Some(msg) = msg {
self.handler.handle_incoming(msg);
} else {
trace!("Stream closed by remote peer.");
return Ok(Async::Ready(()));
}
}
if self.handler.is_finished() {
trace!("inner client finished, exiting...");
Ok(Async::Ready(()))
} else {
trace!("notifying the reactor that we're not done yet");
Ok(Async::NotReady)
}
}
}
pub fn serve<'a, S: Service + 'a, T: AsyncRead + AsyncWrite + 'a + Send>(
stream: T,
service: S,
) -> impl Future<Item = (), Error = io::Error> + 'a + Send {
ServerEndpoint::new(stream, service)
}
struct ServerEndpoint<S: Service, T: AsyncRead + AsyncWrite> {
inner: InnerEndpoint<Server<S>, T>,
}
impl<S: Service, T: AsyncRead + AsyncWrite> ServerEndpoint<S, T> {
pub fn new(stream: T, service: S) -> Self {
ServerEndpoint {
inner: InnerEndpoint {
stream: Transport(Codec.framed(stream)),
handler: Server::new(service),
},
}
}
}
impl<S: Service, T: AsyncRead + AsyncWrite> Future for ServerEndpoint<S, T> {
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.inner.poll()
}
}
pub struct Endpoint<S: ServiceWithClient, T: AsyncRead + AsyncWrite> {
inner: InnerEndpoint<ClientAndServer<S>, T>,
}
impl<S: ServiceWithClient, T: AsyncRead + AsyncWrite> Endpoint<S, T> {
pub fn new(stream: T, service: S) -> Self {
let (inner_client, client) = InnerClient::new();
Endpoint {
inner: InnerEndpoint {
stream: Transport(Codec.framed(stream)),
handler: ClientAndServer {
inner_client,
client,
server: Server::new(service),
},
},
}
}
pub fn client(&self) -> Client {
self.inner.handler.client.clone()
}
}
impl<S: ServiceWithClient, T: AsyncRead + AsyncWrite> Future for Endpoint<S, T> {
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.inner.poll()
}
}
#[derive(Clone)]
pub struct Client {
requests_tx: RequestTx,
notifications_tx: NotificationTx,
}
impl Client {
pub fn new<T: AsyncRead + AsyncWrite + 'static + Send>(stream: T) -> Self {
let (inner_client, client) = InnerClient::new();
let endpoint = InnerEndpoint {
stream: Transport(Codec.framed(stream)),
handler: inner_client,
};
tokio::spawn(
endpoint.map_err(|e| trace!("Client endpoint closed because of an error: {}", e)),
);
client
}
fn from_channels(requests_tx: RequestTx, notifications_tx: NotificationTx) -> Self {
Client {
requests_tx,
notifications_tx,
}
}
pub fn request(&self, method: &str, params: &[Value]) -> Response {
trace!("New request (method={}, params={:?})", method, params);
let request = Request {
id: 0,
method: method.to_owned(),
params: Vec::from(params),
};
let (tx, rx) = oneshot::channel();
let _ = mpsc::UnboundedSender::unbounded_send(&self.requests_tx, (request, tx));
Response(rx)
}
pub fn notify(&self, method: &str, params: &[Value]) -> Ack {
trace!("New notification (method={}, params={:?})", method, params);
let notification = Notification {
method: method.to_owned(),
params: Vec::from(params),
};
let (tx, rx) = oneshot::channel();
let _ = mpsc::UnboundedSender::unbounded_send(&self.notifications_tx, (notification, tx));
Ack(rx)
}
}
impl Future for Client {
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::Ready(()))
}
}