refactor: move things into event module

This commit is contained in:
Fabian Freyer 2019-03-23 00:49:09 -04:00
parent 04f1013f93
commit 4f3e8f6443
3 changed files with 90 additions and 78 deletions

68
src/event.rs Normal file
View File

@ -0,0 +1,68 @@
use actix::Message;
use actix_web::Binary;
use futures::{Future, Poll};
use libc::c_ushort;
use tokio_pty_process::PtyMaster;
pub use crate::terminado::TerminadoMessage;
use tokio_codec::{BytesCodec, Decoder};
type BytesMut = <BytesCodec as Decoder>::Item;
pub struct Resize<T: PtyMaster> {
pty: T,
rows: c_ushort,
cols: c_ushort,
}
impl<T: PtyMaster> Resize<T> {
pub fn new(pty: T, rows: c_ushort, cols: c_ushort) -> Self {
Self { pty, rows, cols }
}
}
impl<T: PtyMaster> Future for Resize<T> {
type Item = ();
type Error = std::io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.pty.resize(self.rows, self.cols)
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct IO(pub BytesMut);
impl Message for IO {
type Result = ();
}
impl Into<Binary> for IO {
fn into(self) -> Binary {
self.0.into()
}
}
impl AsRef<[u8]> for IO {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<Binary> for IO {
fn from(b: Binary) -> Self {
Self(b.as_ref().into())
}
}
impl From<String> for IO {
fn from(s: String) -> Self {
Self(s.into())
}
}
impl From<&str> for IO {
fn from(s: &str) -> Self {
Self(s.into())
}
}

View File

@ -42,63 +42,22 @@ extern crate log;
extern crate pretty_env_logger; extern crate pretty_env_logger;
use actix::*; use actix::*;
use actix_web::{fs::NamedFile, fs::StaticFiles, server, ws, App, Binary, HttpRequest, Result}; use actix_web::{fs::NamedFile, fs::StaticFiles, server, ws, App, HttpRequest, Result};
use futures::prelude::*; use futures::prelude::*;
use libc::c_ushort;
use std::io::Write; use std::io::Write;
use std::process::Command; use std::process::Command;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio_codec::{BytesCodec, Decoder, FramedRead}; use tokio_codec::{BytesCodec, Decoder, FramedRead};
use tokio_pty_process::{AsyncPtyMaster, AsyncPtyMasterWriteHalf, Child, CommandExt, PtyMaster}; use tokio_pty_process::{AsyncPtyMaster, AsyncPtyMasterWriteHalf, Child, CommandExt};
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5); const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
const CLIENT_TIMEOUT: Duration = Duration::from_secs(10); const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
type BytesMut = <BytesCodec as Decoder>::Item; mod event;
mod terminado; mod terminado;
use crate::terminado::TerminadoMessage;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct IO(BytesMut);
impl Message for IO {
type Result = ();
}
impl Into<Binary> for IO {
fn into(self) -> Binary {
self.0.into()
}
}
impl AsRef<[u8]> for IO {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl From<Binary> for IO {
fn from(b: Binary) -> Self {
Self(b.as_ref().into())
}
}
impl From<String> for IO {
fn from(s: String) -> Self {
Self(s.into())
}
}
impl From<&str> for IO {
fn from(s: &str) -> Self {
Self(s.into())
}
}
struct Websocket { struct Websocket {
cons: Option<Addr<Terminal>>, cons: Option<Addr<Terminal>>,
@ -129,29 +88,29 @@ impl Actor for Websocket {
} }
} }
impl Handler<IO> for Websocket { impl Handler<event::IO> for Websocket {
type Result = (); type Result = ();
fn handle(&mut self, msg: IO, ctx: &mut <Self as Actor>::Context) { fn handle(&mut self, msg: event::IO, ctx: &mut <Self as Actor>::Context) {
trace!("Websocket <- Terminal : {:?}", msg); trace!("Websocket <- Terminal : {:?}", msg);
ctx.binary(msg); ctx.binary(msg);
} }
} }
impl Handler<TerminadoMessage> for Websocket { impl Handler<event::TerminadoMessage> for Websocket {
type Result = (); type Result = ();
fn handle(&mut self, msg: TerminadoMessage, ctx: &mut <Self as Actor>::Context) { fn handle(&mut self, msg: event::TerminadoMessage, ctx: &mut <Self as Actor>::Context) {
trace!("Websocket <- Terminal : {:?}", msg); trace!("Websocket <- Terminal : {:?}", msg);
match msg { match msg {
TerminadoMessage::Stdout(_) => { event::TerminadoMessage::Stdout(_) => {
let json = serde_json::to_string(&msg); let json = serde_json::to_string(&msg);
if let Ok(json) = json { if let Ok(json) = json {
ctx.text(json); ctx.text(json);
} }
} }
_ => error!(r#"Invalid TerminadoMessage to Websocket: only "stdout" supported"#), _ => error!(r#"Invalid event::TerminadoMessage to Websocket: only "stdout" supported"#),
} }
} }
} }
@ -200,14 +159,14 @@ impl StreamHandler<ws::Message, ws::ProtocolError> for Websocket {
ws::Message::Pong(_) => self.hb = Instant::now(), ws::Message::Pong(_) => self.hb = Instant::now(),
ws::Message::Text(t) => { ws::Message::Text(t) => {
// Attempt to parse the message as JSON. // Attempt to parse the message as JSON.
if let Ok(tmsg) = TerminadoMessage::from_json(&t) { if let Ok(tmsg) = event::TerminadoMessage::from_json(&t) {
cons.do_send(tmsg); cons.do_send(tmsg);
} else { } else {
// Otherwise, it's just byte data. // Otherwise, it's just byte data.
cons.do_send(IO::from(t)); cons.do_send(event::IO::from(t));
} }
} }
ws::Message::Binary(b) => cons.do_send(IO::from(b)), ws::Message::Binary(b) => cons.do_send(event::IO::from(b)),
ws::Message::Close(_) => ctx.stop(), ws::Message::Close(_) => ctx.stop(),
}; };
} }
@ -231,7 +190,7 @@ impl Terminal {
impl StreamHandler<<BytesCodec as Decoder>::Item, <BytesCodec as Decoder>::Error> for Terminal { impl StreamHandler<<BytesCodec as Decoder>::Item, <BytesCodec as Decoder>::Error> for Terminal {
fn handle(&mut self, msg: <BytesCodec as Decoder>::Item, _ctx: &mut Self::Context) { fn handle(&mut self, msg: <BytesCodec as Decoder>::Item, _ctx: &mut Self::Context) {
self.ws.do_send(TerminadoMessage::Stdout(IO(msg))); self.ws.do_send(event::TerminadoMessage::Stdout(event::IO(msg)));
} }
} }
@ -296,10 +255,10 @@ impl Actor for Terminal {
} }
} }
impl Handler<IO> for Terminal { impl Handler<event::IO> for Terminal {
type Result = (); type Result = ();
fn handle(&mut self, msg: IO, ctx: &mut <Self as Actor>::Context) { fn handle(&mut self, msg: event::IO, ctx: &mut <Self as Actor>::Context) {
let pty = match self.pty_write { let pty = match self.pty_write {
Some(ref mut p) => p, Some(ref mut p) => p,
None => { None => {
@ -318,25 +277,10 @@ impl Handler<IO> for Terminal {
} }
} }
struct Resize<T: PtyMaster> { impl Handler<event::TerminadoMessage> for Terminal {
pty: T,
rows: c_ushort,
cols: c_ushort,
}
impl<T: PtyMaster> Future for Resize<T> {
type Item = ();
type Error = std::io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.pty.resize(self.rows, self.cols)
}
}
impl Handler<TerminadoMessage> for Terminal {
type Result = (); type Result = ();
fn handle(&mut self, msg: TerminadoMessage, ctx: &mut <Self as Actor>::Context) { fn handle(&mut self, msg: event::TerminadoMessage, ctx: &mut <Self as Actor>::Context) {
let pty = match self.pty_write { let pty = match self.pty_write {
Some(ref mut p) => p, Some(ref mut p) => p,
None => { None => {
@ -348,20 +292,20 @@ impl Handler<TerminadoMessage> for Terminal {
trace!("Websocket -> Terminal : {:?}", msg); trace!("Websocket -> Terminal : {:?}", msg);
match msg { match msg {
TerminadoMessage::Stdin(io) => { event::TerminadoMessage::Stdin(io) => {
if let Err(e) = pty.write(io.as_ref()) { if let Err(e) = pty.write(io.as_ref()) {
error!("Could not write to PTY: {}", e); error!("Could not write to PTY: {}", e);
ctx.stop(); ctx.stop();
} }
} }
TerminadoMessage::Resize { cols, rows } => { event::TerminadoMessage::Resize { cols, rows } => {
info!("Resize: cols = {}, rows = {}", cols, rows); info!("Resize: cols = {}, rows = {}", cols, rows);
if let Err(e) = (Resize { pty, cols, rows }).wait() { if let Err(e) = event::Resize::new(pty, cols, rows).wait() {
error!("Resize failed: {}", e); error!("Resize failed: {}", e);
ctx.stop(); ctx.stop();
} }
} }
TerminadoMessage::Stdout(_) => { event::TerminadoMessage::Stdout(_) => {
error!("Invalid Terminado Message: Stdin cannot go to PTY") error!("Invalid Terminado Message: Stdin cannot go to PTY")
} }
}; };

View File

@ -8,7 +8,7 @@ use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use serde_json; use serde_json;
use crate::IO; use crate::event::IO;
impl Message for TerminadoMessage { impl Message for TerminadoMessage {
type Result = (); type Result = ();