Browse Source

Switch from websocket crate to ws crate.

wip
Titouan Rigoudy 9 years ago
parent
commit
5db8544d81
9 changed files with 258 additions and 456 deletions
  1. +17
    -213
      Cargo.lock
  2. +1
    -1
      Cargo.toml
  3. +37
    -26
      src/client.rs
  4. +0
    -186
      src/control/controller.rs
  5. +7
    -2
      src/control/mod.rs
  6. +0
    -7
      src/control/request.rs
  7. +192
    -0
      src/control/ws.rs
  8. +4
    -9
      src/main.rs
  9. +0
    -12
      src/result.rs

+ 17
- 213
Cargo.lock View File

@ -9,7 +9,7 @@ dependencies = [
"mio 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"websocket 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ws 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -54,17 +54,6 @@ name = "cfg-if"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cookie"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "encoding"
version = "0.2.32"
@ -140,48 +129,11 @@ dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gdi32-sys"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hpack"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "httparse"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cookie 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.1"
@ -191,16 +143,6 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.1.12"
@ -211,14 +153,6 @@ name = "libc"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libressl-pnacl-sys"
version = "2.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.5"
@ -240,15 +174,6 @@ dependencies = [
"libc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mime"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
version = "0.5.0"
@ -298,67 +223,6 @@ dependencies = [
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys-extras 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl-sys"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl-sys-extras"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pnacl-build-helper"
version = "1.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.3.13"
@ -403,24 +267,11 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.6.15"
name = "sha1"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -428,23 +279,6 @@ name = "slab"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "solicit"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempdir"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.34"
@ -455,24 +289,6 @@ dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.2.3"
@ -498,15 +314,6 @@ dependencies = [
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "user32-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf8-ranges"
version = "0.1.3"
@ -521,22 +328,6 @@ dependencies = [
"rustc-serialize 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "websocket"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.5"
@ -547,6 +338,19 @@ name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ws"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"sha1 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"


+ 1
- 1
Cargo.toml View File

@ -11,4 +11,4 @@ log = "^0.3.5"
mio = "^0.5"
rust-crypto = "^0.2.34"
rustc-serialize = "^0.3.17"
websocket = "^0.15.0"
ws = "^0.4"

+ 37
- 26
src/client.rs View File

@ -12,7 +12,7 @@ use user;
#[derive(Debug)]
enum IncomingMessage {
ServerResponse(ServerResponse),
ControlRequest(control::Request),
ControlNotification(control::Notification),
}
#[derive(Debug, Clone)]
@ -26,9 +26,8 @@ pub struct Client {
proto_tx: mio::Sender<Request>,
proto_rx: mpsc::Receiver<Response>,
control_tx: mpsc::Sender<control::Response>,
control_rx: mpsc::Receiver<control::Request>,
controller_connected: bool,
control_tx: Option<control::Sender>,
control_rx: mpsc::Receiver<control::Notification>,
login_status: LoginStatus,
@ -40,17 +39,15 @@ impl Client {
pub fn new(
proto_tx: mio::Sender<Request>,
proto_rx: mpsc::Receiver<Response>,
control_tx: mpsc::Sender<control::Response>,
control_rx: mpsc::Receiver<control::Request>)
control_rx: mpsc::Receiver<control::Notification>)
-> Self
{
Client {
proto_tx: proto_tx,
proto_rx: proto_rx,
control_tx: control_tx,
control_tx: None,
control_rx: control_rx,
controller_connected: false,
login_status: LoginStatus::Pending,
@ -74,8 +71,8 @@ impl Client {
IncomingMessage::ServerResponse(response) =>
self.handle_server_response(response),
IncomingMessage::ControlRequest(request) =>
self.handle_control_request(request),
IncomingMessage::ControlNotification(notif) =>
self.handle_control_notification(notif),
}
}
}
@ -83,7 +80,7 @@ impl Client {
// Necessary to break out in different function because self cannot be
// borrowed in the select arms due to *macro things*.
fn recv(&mut self) -> IncomingMessage {
let proto_rx = &self.proto_rx;
let proto_rx = &self.proto_rx;
let control_rx = &self.control_rx;
select! {
result = proto_rx.recv() =>
@ -93,7 +90,7 @@ impl Client {
},
result = control_rx.recv() =>
IncomingMessage::ControlRequest(result.unwrap())
IncomingMessage::ControlNotification(result.unwrap())
}
}
@ -103,11 +100,35 @@ impl Client {
}
/// Send a response to the controller client.
fn control_send(&self, response: control::Response) {
if !self.controller_connected {
return; // Silently drop control packets when no-one is listening.
fn control_send(&mut self, response: control::Response) {
// Silently drop control packets when no-one is listening.
if let Some(ref mut control_tx) = self.control_tx {
control_tx.send(response).unwrap();
}
}
/*===============================*
* CONTROL NOTIFICATION HANDLING *
*===============================*/
fn handle_control_notification(&mut self, notif: control::Notification) {
match notif {
control::Notification::Connected(tx) => {
self.control_tx = Some(tx);
},
control::Notification::Disconnected => {
self.control_tx = None;
},
control::Notification::Error(e) => {
debug!("Control loop error: {}", e);
self.control_tx = None;
},
control::Notification::Request(req) =>
self.handle_control_request(req)
}
self.control_tx.send(response).unwrap();
}
/*==========================*
@ -116,16 +137,6 @@ impl Client {
fn handle_control_request(&mut self, request: control::Request) {
match request {
control::Request::ConnectNotification => {
info!("Controller client connected");
self.controller_connected = true;
},
control::Request::DisconnectNotification => {
info!("Controller client disconnected");
self.controller_connected = false;
},
control::Request::LoginStatusRequest =>
self.handle_login_status_request(),


+ 0
- 186
src/control/controller.rs View File

@ -1,186 +0,0 @@
use std::sync::mpsc;
use std::str;
use std::thread;
use rustc_serialize::json;
use websocket;
use websocket::{Receiver, Sender};
use config;
use result;
use super::request::*;
use super::response::*;
type WebSocketReceiver =
websocket::receiver::Receiver<websocket::WebSocketStream>;
type WebSocketSender =
websocket::sender::Sender<websocket::WebSocketStream>;
type WebSocketClient =
websocket::Client<websocket::DataFrame, WebSocketSender, WebSocketReceiver>;
pub struct Controller {
client_tx: mpsc::Sender<Request>,
client_rx: mpsc::Receiver<Response>,
}
impl Controller {
pub fn new(tx: mpsc::Sender<Request>,
rx: mpsc::Receiver<Response>)
-> Self
{
Controller {
client_tx: tx,
client_rx: rx,
}
}
pub fn run(&mut self) {
let host = config::CONTROL_HOST;
let port = config::CONTROL_PORT;
let mut server = websocket::Server::bind((host, port)).unwrap();
info!("Controller bound to {}:{}", host, port);
loop {
info!("Waiting for controller client");
let client = match Self::try_get_client(&mut server) {
Ok(client) => client,
Err(e) => {
error!("Error accepting control connection: {}", e);
continue;
}
};
// Empty client_rx of any messages that client has sent while
// no-one was connected.
while let Ok(_) = self.client_rx.try_recv() { /* continue */ }
// Notify client that a controller is connected.
self.client_tx.send(Request::ConnectNotification).unwrap();
let (sender, receiver) = client.split();
let (sender_tx, sender_rx) = mpsc::channel();
// Handle incoming messages from controller in a separate thread,
// and forward them to the client through client_tx.
let tx = self.client_tx.clone();
let handle = thread::spawn(move || {
Self::receiver_loop(receiver, tx, sender_tx);
});
// Handle messages from client and forward them to the controller.
Self::sender_loop(sender, &mut self.client_rx, sender_rx);
// Sender loop has terminated, wait for receiver loop too.
handle.join();
// Notify client that the controller has disconnected.
self.client_tx.send(Request::DisconnectNotification).unwrap();
}
}
fn try_get_client(server: &mut websocket::Server)
-> result::Result<WebSocketClient>
{
let connection = try!(server.accept());
let request = try!(connection.read_request());
let client = try!(request.accept().send());
Ok(client)
}
fn receiver_loop(
mut receiver: WebSocketReceiver,
client_tx: mpsc::Sender<Request>,
sender_tx: mpsc::Sender<()>)
{
for message_result in receiver.incoming_messages() {
let message : websocket::message::Message = match message_result {
Ok(message) => message,
Err(e) => {
warn!("Error receving websocket message: {}", e);
continue;
}
};
match message.opcode {
websocket::message::Type::Text => {
let payload = message.payload;
match Self::handle_text_message(&payload, &client_tx) {
Ok(()) => (),
Err(e) => {
error!("Error handling text message: {}", e);
}
}
},
websocket::message::Type::Close => {
info!("Received close request from controller.");
break;
},
code => warn!(
"Unhandled websocket message with code {:?}", code
),
}
}
info!("Shutting down websocket receiver");
receiver.shutdown().unwrap();
// Notify sender that the websocket is closed
sender_tx.send(());
}
fn handle_text_message(
payload_bytes: &[u8],
client_tx: &mpsc::Sender<Request>)
-> result::Result<()>
{
let payload = try!(str::from_utf8(payload_bytes));
let control_request = try!(json::decode(payload));
debug!("Received control request: {:?}", control_request);
try!(client_tx.send(control_request));
Ok(())
}
fn sender_loop(
mut sender: WebSocketSender,
client_rx: &mut mpsc::Receiver<Response>,
sender_rx: mpsc::Receiver<()>)
{
loop {
select! {
_ = sender_rx.recv() => break,
response_result = client_rx.recv() => {
let response = match response_result {
Ok(response) => response,
Err(e) => {
error!(
"Error receiving from client channel: {}", e
);
break;
}
};
match Self::send_response(&mut sender, response) {
Ok(()) => (),
Err(e) =>
error!("Error sending control response: {}", e),
}
}
}
}
info!("Shutting down websocket sender");
sender.shutdown_all().unwrap();
}
fn send_response(sender: &mut WebSocketSender, response: Response)
-> result::Result<()>
{
debug!("Sending control response: {:?}", response);
let encoded = try!(json::encode(&response));
let message = websocket::Message::text(encoded);
try!(sender.send_message(&message));
Ok(())
}
}

+ 7
- 2
src/control/mod.rs View File

@ -1,7 +1,12 @@
mod controller;
mod request;
mod response;
mod ws;
pub use self::controller::Controller;
pub use self::ws::{
listen,
Notification,
Sender,
SendError,
};
pub use self::request::*;
pub use self::response::*;

+ 0
- 7
src/control/request.rs View File

@ -2,13 +2,6 @@
/// controller client to the client.
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub enum Request {
/// Not a real request: this is to notify the client that a controller is
/// now connected, and control responses can now be sent.
ConnectNotification,
/// Not a real request: this is to notify the client that the controller has
/// now disconnected, and control responses should no longer be
/// sent.
DisconnectNotification,
/// The controller wants to join a room. Contains the room name.
RoomJoinRequest(String),
/// The controller wants to leave a rom. Contains the room name.


+ 192
- 0
src/control/ws.rs View File

@ -0,0 +1,192 @@
use std::error;
use std::fmt;
use std::sync::mpsc;
use rustc_serialize::json;
use ws;
use config;
use super::request::*;
use super::response::*;
/// This enum contains the possible notifications that the control loop will
/// send to the client.
#[derive(Debug)]
pub enum Notification {
/// A new controller has connected: control messages can now be sent on the
/// given channel.
Connected(Sender),
/// The controller has disconnected.
Disconnected,
/// An irretrievable error has arisen.
Error(String),
/// The controller has sent a request.
Request(Request),
}
/// This error is returned when a `Sender` fails to send a control request.
#[derive(Debug)]
pub enum SendError {
/// Error encoding the control request.
JSONEncoderError(json::EncoderError),
/// Error sending the encoded control request to the websocket.
WebSocketError(ws::Error),
}
impl fmt::Display for SendError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
SendError::JSONEncoderError(ref err) =>
write!(fmt, "JSONEncoderError: {}", err),
SendError::WebSocketError(ref err) =>
write!(fmt, "WebSocketError: {}", err),
}
}
}
impl error::Error for SendError {
fn description(&self) -> &str {
match *self {
SendError::JSONEncoderError(_) => "JSONEncoderError",
SendError::WebSocketError(_) => "WebSocketError",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
SendError::JSONEncoderError(ref err) => Some(err),
SendError::WebSocketError(ref err) => Some(err),
}
}
}
impl From<json::EncoderError> for SendError {
fn from(err: json::EncoderError) -> Self {
SendError::JSONEncoderError(err)
}
}
impl From<ws::Error> for SendError {
fn from(err: ws::Error) -> Self {
SendError::WebSocketError(err)
}
}
/// This struct is used to send control responses to the controller.
/// It encapsulates the websocket connection so as to isolate clients from
/// the underlying implementation.
#[derive(Clone, Debug)]
pub struct Sender {
sender: ws::Sender,
}
impl Sender {
/// Queues up a control response to be sent to the controller.
pub fn send(&mut self, response: Response) -> Result<(), SendError> {
let encoded = try!(json::encode(&response));
try!(self.sender.send(encoded));
Ok(())
}
}
/// This struct handles a single websocket connection.
#[derive(Debug)]
struct Handler {
/// The channel on which to send notifications to the client.
client_tx: mpsc::Sender<Notification>,
/// The channel on which to send messages to the controller.
socket_tx: ws::Sender,
}
impl Handler {
fn send_to_client(&self, notification: Notification) -> ws::Result<()> {
match self.client_tx.send(notification) {
Ok(()) => Ok(()),
Err(e)=> {
error!("Error sending notification to client: {}", e);
Err(ws::Error::new(ws::ErrorKind::Internal, ""))
}
}
}
}
impl ws::Handler for Handler {
fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
info!("Websocket open");
self.send_to_client(Notification::Connected(Sender {
sender: self.socket_tx.clone()
}))
}
fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
info!("Websocket closed: code: {:?}, reason: {:?}", code, reason);
self.send_to_client(Notification::Disconnected).unwrap_or(())
}
fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
// Get the payload string.
let payload = match msg {
ws::Message::Text(payload) => payload,
ws::Message::Binary(_) => {
error!("Received binary websocket message from controller");
return Err(ws::Error::new(
ws::ErrorKind::Protocol, "Binary message not supported"
))
}
};
// Decode the json control request.
let control_request = match json::decode(&payload) {
Ok(control_request) => control_request,
Err(e) => {
error!("Received invalid JSON message from controller: {}", e);
return Err(ws::Error::new(
ws::ErrorKind::Protocol, "Invalid JSON"
))
}
};
debug!("Received control request: {:?}", control_request);
// Send the control request to the client.
self.send_to_client(Notification::Request(control_request))
}
}
/// Start listening on the socket address stored in configuration, and send
/// control notifications to the client through the given channel.
pub fn listen(client_tx: mpsc::Sender<Notification>) {
let websocket_result = ws::Builder::new().with_settings(ws::Settings {
max_connections: 1,
..ws::Settings::default()
}).build(|socket_tx| Handler {
client_tx: client_tx.clone(),
socket_tx: socket_tx,
});
let websocket = match websocket_result {
Ok(websocket) => websocket,
Err(e) => {
error!("Unable to build websocket: {}", e);
client_tx.send(Notification::Error(
format!("Unable to build websocket: {}", e)
)).unwrap();
return
}
};
let listen_result = websocket.listen(
(config::CONTROL_HOST, config::CONTROL_PORT)
);
match listen_result {
Ok(_) => (),
Err(e) => {
error!("Unable to listen on websocket: {}", e);
client_tx.send(Notification::Error(
format!("Unable to listen on websocket: {}", e)
)).unwrap();
}
}
}

+ 4
- 9
src/main.rs View File

@ -17,7 +17,7 @@ extern crate encoding;
extern crate env_logger;
extern crate mio;
extern crate rustc_serialize;
extern crate websocket;
extern crate ws;
use std::sync::mpsc::channel;
use std::thread;
@ -25,7 +25,6 @@ use std::thread;
use mio::EventLoop;
use client::Client;
use control::Controller;
use handler::ConnectionHandler;
fn main() {
@ -47,7 +46,6 @@ fn main() {
let (handler_to_client_tx, handler_to_client_rx) = channel();
let (control_to_client_tx, control_to_client_rx) = channel();
let (client_to_control_tx, client_to_control_rx) = channel();
let client_to_handler_tx = event_loop.channel();
let mut handler = {
@ -65,13 +63,10 @@ fn main() {
};
let mut client = Client::new(
client_to_handler_tx, handler_to_client_rx,
client_to_control_tx, control_to_client_rx);
client_to_handler_tx, handler_to_client_rx, control_to_client_rx
);
let mut controller =
Controller::new(control_to_client_tx, client_to_control_rx);
thread::spawn(move || controller.run());
thread::spawn(move || control::listen(control_to_client_tx));
thread::spawn(move || event_loop.run(&mut handler).unwrap());
client.run();
}

+ 0
- 12
src/result.rs View File

@ -6,7 +6,6 @@ use std::str;
use std::sync::mpsc;
use rustc_serialize::json;
use websocket;
use control;
use proto;
@ -20,7 +19,6 @@ pub enum Error {
SendControlRequestError(mpsc::SendError<control::Request>),
SendProtoResponseError(mpsc::SendError<proto::Response>),
Utf8Error(str::Utf8Error),
WebSocketError(websocket::result::WebSocketError),
}
impl fmt::Display for Error {
@ -40,8 +38,6 @@ impl fmt::Display for Error {
write!(fmt, "SendProtoResponseError: {}", err),
Error::Utf8Error(ref err) =>
write!(fmt, "Utf8Error: {}", err),
Error::WebSocketError(ref err) =>
write!(fmt, "WebSocketError: {}", err),
}
}
}
@ -56,7 +52,6 @@ impl error::Error for Error {
Error::SendControlRequestError(_) => "SendControlRequestError",
Error::SendProtoResponseError(_) => "SendProtoResponseError",
Error::Utf8Error(_) => "Utf8Error",
Error::WebSocketError(_) => "WebSocketError",
}
}
@ -69,7 +64,6 @@ impl error::Error for Error {
Error::SendControlRequestError(ref err) => Some(err),
Error::SendProtoResponseError(ref err) => Some(err),
Error::Utf8Error(ref err) => Some(err),
Error::WebSocketError(ref err) => Some(err),
}
}
}
@ -116,10 +110,4 @@ impl From<str::Utf8Error> for Error {
}
}
impl From<websocket::result::WebSocketError> for Error {
fn from(err: websocket::result::WebSocketError) -> Self {
Error::WebSocketError(err)
}
}
pub type Result<T> = result::Result<T, Error>;

Loading…
Cancel
Save