From 8cbee2fcc5b0708cec61d9bfe4de675d2e5d7daf Mon Sep 17 00:00:00 2001 From: CodeSteak Date: Thu, 25 Apr 2019 23:37:16 +0200 Subject: [PATCH] restructre server network files --- .../src/protocol/{results.rs => error.rs} | 0 .../{protocol_connection.rs => connection.rs} | 102 +----------- .../protocol/implementation/listen_forever.rs | 137 ++++++++++++++++ .../src/protocol/implementation/mod.rs | 146 +----------------- .../src/protocol/implementation/package.rs | 96 ++++++++++++ .../texture-sync-server/src/protocol/mod.rs | 11 +- 6 files changed, 245 insertions(+), 247 deletions(-) rename server/texture-sync-server/src/protocol/{results.rs => error.rs} (100%) rename server/texture-sync-server/src/protocol/implementation/{protocol_connection.rs => connection.rs} (81%) create mode 100644 server/texture-sync-server/src/protocol/implementation/listen_forever.rs create mode 100644 server/texture-sync-server/src/protocol/implementation/package.rs diff --git a/server/texture-sync-server/src/protocol/results.rs b/server/texture-sync-server/src/protocol/error.rs similarity index 100% rename from server/texture-sync-server/src/protocol/results.rs rename to server/texture-sync-server/src/protocol/error.rs diff --git a/server/texture-sync-server/src/protocol/implementation/protocol_connection.rs b/server/texture-sync-server/src/protocol/implementation/connection.rs similarity index 81% rename from server/texture-sync-server/src/protocol/implementation/protocol_connection.rs rename to server/texture-sync-server/src/protocol/implementation/connection.rs index 85162f3..f885a0d 100644 --- a/server/texture-sync-server/src/protocol/implementation/protocol_connection.rs +++ b/server/texture-sync-server/src/protocol/implementation/connection.rs @@ -1,106 +1,10 @@ -use crate::model::*; +use super::*; -use serde::{Deserialize, Serialize}; - -// TODO: put conversion and these enums in own file. - -#[derive(Eq, PartialEq, Clone, Debug)] -pub enum Package { - Json(JsonValue), - Command(Command), - Binary(Vec), - Error(u16, String), -} - -#[derive(Eq, PartialEq, Clone, Debug)] -pub enum JsonValue { - Null, - True, - False, - Texture(Texture), - TextureArray(Vec), -} - -#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)] -pub enum Command { - #[serde(rename = "ping")] - Ping {}, - #[serde(rename = "pong")] - Pong {}, - #[serde(rename = "query")] - Query { query: Vec }, - #[serde(rename = "get_texture")] - GetTexture { - id: Option, - name: Option, - }, - #[serde(rename = "get_texture_file")] - GetTextureData { texture_hash: Sha256 }, - #[serde(rename = "get_texture_preview")] - GetTexturePreview { - texture_hash: Sha256, - desired_format: TextureFormat, - }, - #[serde(rename = "replace_texture")] - ReplaceTexture { - old: Option, - new: Option, - }, -} - -use super::results::*; - -impl From for Package { - fn from(item: ProtocolError) -> Self { - match item { - ProtocolError::BadRequest(msg) => Package::Error(400, msg), - ProtocolError::FileNotFound(msg) => Package::Error(404, msg), - ProtocolError::Conflict(msg) => Package::Error(409, msg), - ProtocolError::InternalServerError(_err) => { - Package::Error(500, "Internal Server Error.".to_string()) - } - ProtocolError::NotImplemented => Package::Error( - 501, - "Well, I'm sorry, \ - but this feature is still a Todo :/" - .to_string(), - ), - } - } -} - -impl From>> for Package { - fn from(item: ProtocolResult>) -> Self { - match item { - Ok(textures) => Package::Json(JsonValue::TextureArray(textures)), - Err(err) => Package::from(err), - } - } -} - -impl From>> for Package { - fn from(item: ProtocolResult>) -> Self { - match item { - Ok(Some(texture)) => Package::Json(JsonValue::Texture(texture)), - Ok(None) => Package::Json(JsonValue::Null), - Err(err) => Package::from(err), - } - } -} - -impl From>> for Package { - fn from(item: ProtocolResult>) -> Self { - match item { - Ok(bin) => Package::Binary(bin), - Err(err) => Package::from(err), - } - } -} - -use crate::protocol::results::ProtocolResult; use std::io::*; use std::net::*; +use serde::{Deserialize, Serialize}; + pub struct Connection { reader: R, writer: W, diff --git a/server/texture-sync-server/src/protocol/implementation/listen_forever.rs b/server/texture-sync-server/src/protocol/implementation/listen_forever.rs new file mode 100644 index 0000000..b60c792 --- /dev/null +++ b/server/texture-sync-server/src/protocol/implementation/listen_forever.rs @@ -0,0 +1,137 @@ +use std::io::*; +use std::net::*; + +use std::thread; +use std::time::Duration; + +use super::*; + +pub fn listen_forever(handler: H, config: &ProtocolConfig) -> io::Result<()> + where + H: 'static + ProtocolHandler + Sized, +{ + let listener = TcpListener::bind((config.listen_addr.as_str(), config.port))?; + + for mut connection in listener.incoming() { + // If there is an successful connection, + // set timeouts. + // We ignore errors here, so they will be caught in the clients thread. + let _ = connection.as_mut().map(|stream| { + stream.set_read_timeout(Duration::from_secs(config.read_timeout_s).into())?; + stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into()) + }); + + let handler = handler.clone(); + let _ = thread::spawn(move || client_loop(connection?, handler)); + } + + Ok(()) +} + +fn client_loop(connection: TcpStream, mut handler: H) -> io::Result<()> + where + H: 'static + ProtocolHandler + Sized, +{ + let mut connection = Connection::from_tcp(connection)?; + 'outer: loop { + let package = connection.receive()?; + + match package { + Package::Error(_, _) => { + // Just close the connection. + break; + } + + Package::Json(_) | Package::Binary(_) => { + connection.send(&Package::Error(400, "Expected Command.".to_string()))?; + break; + } + + Package::Command(Command::Ping {}) => { + connection.send(&Package::Command(Command::Pong {}))?; + } + + Package::Command(Command::Pong {}) => { + // Ignore + } + + Package::Command(Command::Query { query }) => { + connection.send(&Package::from(handler.query(&query[..])))?; + } + + Package::Command(Command::GetTexture { id, name }) => match (id, name) { + (Some(id), None) => { + connection.send(&Package::from(handler.get_texture_by_id(&id)))?; + } + (None, Some(name)) => { + connection.send(&Package::from(handler.get_texture_by_name(&name)))?; + } + _ => { + connection.send(&Package::from(ProtocolError::BadRequest( + "Either 'id' or 'name' must be set!".to_string(), + )))?; + } + }, + + Package::Command(Command::GetTextureData { texture_hash }) => { + connection.send(&Package::from(handler.get_texture_file(texture_hash)))?; + } + + Package::Command(Command::GetTexturePreview { + texture_hash, + desired_format, + }) => { + connection.send(&Package::from( + handler.get_texture_preview(texture_hash, desired_format), + ))?; + } + + // TODO: use less nesting. + Package::Command(Command::ReplaceTexture { old, new }) => { + match handler.replace_texture(old.clone(), new.clone(), None) { + Ok(ReplaceTextureStatus::Ok) => { + connection.send(&Package::Json(JsonValue::True))?; + } + Ok(ReplaceTextureStatus::NeedTextureData(hash)) => { + connection.send(&Package::Command(Command::GetTextureData { + texture_hash: hash, + }))?; + + let pkg = connection.receive()?; + match pkg { + Package::Binary(data) => { + match handler.replace_texture(old.clone(), new.clone(), Some(data)) + { + Ok(ReplaceTextureStatus::Ok) => { + connection.send(&Package::Json(JsonValue::True))?; + } + Ok(ReplaceTextureStatus::NeedTextureData(hash)) => { + panic!("Contract Violation: handler must not return NeedTextureData \ + when data is given."); + } + Err(err) => { + connection.send(&Package::from(err))?; + } + } + } + Package::Error(_, _) => { + // Just close the connection. + break 'outer; + } + _ => { + connection.send(&Package::from(ProtocolError::BadRequest( + "Expected Texture Data!".to_string(), + )))?; + } + } + } + Err(err) => { + connection.send(&Package::from(err))?; + } + } + } + } + } + + Ok(()) +} diff --git a/server/texture-sync-server/src/protocol/implementation/mod.rs b/server/texture-sync-server/src/protocol/implementation/mod.rs index 8903aee..43e83c3 100644 --- a/server/texture-sync-server/src/protocol/implementation/mod.rs +++ b/server/texture-sync-server/src/protocol/implementation/mod.rs @@ -1,144 +1,10 @@ use super::*; -use std::io::*; -use std::net::*; +mod connection; +use self::connection::*; -use std::thread; -use std::time::Duration; +mod listen_forever; +pub use self::listen_forever::*; -use crate::model::*; - -mod protocol_connection; -use self::protocol_connection::*; - -use super::results::*; - -pub fn listen_forever(handler: H, config: &ProtocolConfig) -> io::Result<()> -where - H: 'static + ProtocolHandler + Sized, -{ - let listener = TcpListener::bind((config.listen_addr.as_str(), config.port))?; - - for mut connection in listener.incoming() { - // If there is an successful connection, - // set timeouts. - // We ignore errors here, so they will be caught in the clients thread. - let _ = connection.as_mut().map(|stream| { - stream.set_read_timeout(Duration::from_secs(config.read_timeout_s).into())?; - stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into()) - }); - - let handler = handler.clone(); - let _ = thread::spawn(move || client_loop(connection?, handler)); - } - - Ok(()) -} - -fn client_loop(connection: TcpStream, mut handler: H) -> io::Result<()> -where - H: 'static + ProtocolHandler + Sized, -{ - let mut connection = Connection::from_tcp(connection)?; - 'outer: loop { - let package = connection.receive()?; - - match package { - Package::Error(_, _) => { - // Just close the connection. - break; - } - - Package::Json(_) | Package::Binary(_) => { - connection.send(&Package::Error(400, "Expected Command.".to_string()))?; - break; - } - - Package::Command(Command::Ping {}) => { - connection.send(&Package::Command(Command::Pong {}))?; - } - - Package::Command(Command::Pong {}) => { - // Ignore - } - - Package::Command(Command::Query { query }) => { - connection.send(&Package::from(handler.query(&query[..])))?; - } - - Package::Command(Command::GetTexture { id, name }) => match (id, name) { - (Some(id), None) => { - connection.send(&Package::from(handler.get_texture_by_id(&id)))?; - } - (None, Some(name)) => { - connection.send(&Package::from(handler.get_texture_by_name(&name)))?; - } - _ => { - connection.send(&Package::from(ProtocolError::BadRequest( - "Either 'id' or 'name' must be set!".to_string(), - )))?; - } - }, - - Package::Command(Command::GetTextureData { texture_hash }) => { - connection.send(&Package::from(handler.get_texture_file(texture_hash)))?; - } - - Package::Command(Command::GetTexturePreview { - texture_hash, - desired_format, - }) => { - connection.send(&Package::from( - handler.get_texture_preview(texture_hash, desired_format), - ))?; - } - - // TODO: use less nesting. - Package::Command(Command::ReplaceTexture { old, new }) => { - match handler.replace_texture(old.clone(), new.clone(), None) { - Ok(ReplaceTextureStatus::Ok) => { - connection.send(&Package::Json(JsonValue::True))?; - } - Ok(ReplaceTextureStatus::NeedTextureData(hash)) => { - connection.send(&Package::Command(Command::GetTextureData { - texture_hash: hash, - }))?; - - let pkg = connection.receive()?; - match pkg { - Package::Binary(data) => { - match handler.replace_texture(old.clone(), new.clone(), Some(data)) - { - Ok(ReplaceTextureStatus::Ok) => { - connection.send(&Package::Json(JsonValue::True))?; - } - Ok(ReplaceTextureStatus::NeedTextureData(hash)) => { - panic!("Contract Violation: handler must not return NeedTextureData \ - when data is given."); - } - Err(err) => { - connection.send(&Package::from(err))?; - } - } - } - Package::Error(_, _) => { - // Just close the connection. - break 'outer; - } - _ => { - connection.send(&Package::from(ProtocolError::BadRequest( - "Expected Texture Data!".to_string(), - )))?; - } - } - } - Err(err) => { - connection.send(&Package::from(err))?; - } - } - } - } - } - - Ok(()) -} +mod package; +use self::package::*; diff --git a/server/texture-sync-server/src/protocol/implementation/package.rs b/server/texture-sync-server/src/protocol/implementation/package.rs new file mode 100644 index 0000000..5ad6a83 --- /dev/null +++ b/server/texture-sync-server/src/protocol/implementation/package.rs @@ -0,0 +1,96 @@ +use crate::model::*; + +use serde::{Deserialize, Serialize}; + +#[derive(Eq, PartialEq, Clone, Debug)] +pub enum Package { + Json(JsonValue), + Command(Command), + Binary(Vec), + Error(u16, String), +} + +#[derive(Eq, PartialEq, Clone, Debug)] +pub enum JsonValue { + Null, + True, + False, + Texture(Texture), + TextureArray(Vec), +} + +#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)] +pub enum Command { + #[serde(rename = "ping")] + Ping {}, + #[serde(rename = "pong")] + Pong {}, + #[serde(rename = "query")] + Query { query: Vec }, + #[serde(rename = "get_texture")] + GetTexture { + id: Option, + name: Option, + }, + #[serde(rename = "get_texture_file")] + GetTextureData { texture_hash: Sha256 }, + #[serde(rename = "get_texture_preview")] + GetTexturePreview { + texture_hash: Sha256, + desired_format: TextureFormat, + }, + #[serde(rename = "replace_texture")] + ReplaceTexture { + old: Option, + new: Option, + }, +} + +use super::error::*; + +impl From for Package { + fn from(item: ProtocolError) -> Self { + match item { + ProtocolError::BadRequest(msg) => Package::Error(400, msg), + ProtocolError::FileNotFound(msg) => Package::Error(404, msg), + ProtocolError::Conflict(msg) => Package::Error(409, msg), + ProtocolError::InternalServerError(_err) => { + Package::Error(500, "Internal Server Error.".to_string()) + } + ProtocolError::NotImplemented => Package::Error( + 501, + "Well, I'm sorry, \ + but this feature is still a Todo :/" + .to_string(), + ), + } + } +} + +impl From>> for Package { + fn from(item: ProtocolResult>) -> Self { + match item { + Ok(textures) => Package::Json(JsonValue::TextureArray(textures)), + Err(err) => Package::from(err), + } + } +} + +impl From>> for Package { + fn from(item: ProtocolResult>) -> Self { + match item { + Ok(Some(texture)) => Package::Json(JsonValue::Texture(texture)), + Ok(None) => Package::Json(JsonValue::Null), + Err(err) => Package::from(err), + } + } +} + +impl From>> for Package { + fn from(item: ProtocolResult>) -> Self { + match item { + Ok(bin) => Package::Binary(bin), + Err(err) => Package::from(err), + } + } +} \ No newline at end of file diff --git a/server/texture-sync-server/src/protocol/mod.rs b/server/texture-sync-server/src/protocol/mod.rs index d79564b..966cb33 100644 --- a/server/texture-sync-server/src/protocol/mod.rs +++ b/server/texture-sync-server/src/protocol/mod.rs @@ -1,13 +1,8 @@ -// TODO: remove on implementation -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(dead_code)] - -mod results; -pub use self::results::*; +mod error; +pub use self::error::*; mod implementation; -pub use self::implementation::listen_forever; +pub use self::implementation::*; use crate::model::*;